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.Function;
11 import com.google.common.base.Optional;
12 import com.google.common.collect.Lists;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import java.math.BigInteger;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.Objects;
22 import java.util.Timer;
23 import java.util.TimerTask;
24 import java.util.concurrent.Callable;
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.stream.Collectors;
30 import org.apache.commons.lang3.tuple.ImmutablePair;
31 import org.apache.commons.lang3.tuple.Pair;
32 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
33 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
34 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
35 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
36 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
37 import org.opendaylight.genius.interfacemanager.IfmUtil;
38 import org.opendaylight.genius.mdsalutil.MDSALUtil;
39 import org.opendaylight.genius.utils.SystemPropertyReader;
40 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
41 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
42 import org.opendaylight.genius.utils.hwvtep.HwvtepUtils;
43 import org.opendaylight.netvirt.elan.l2gw.jobs.DeleteL2GwDeviceMacsFromElanJob;
44 import org.opendaylight.netvirt.elan.l2gw.jobs.DeleteLogicalSwitchJob;
45 import org.opendaylight.netvirt.elan.l2gw.listeners.HwvtepTerminationPointListener;
46 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
47 import org.opendaylight.netvirt.elan.utils.ElanConstants;
48 import org.opendaylight.netvirt.elan.utils.ElanUtils;
49 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
50 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.AddL2GwDeviceInputBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInputBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTable;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
82 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
83 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
84 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
85 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
86 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
87 import org.opendaylight.yangtools.yang.common.RpcResult;
88 import org.slf4j.Logger;
89 import org.slf4j.LoggerFactory;
92 * It gathers a set of utility methods that handle ELAN configuration in
93 * external Devices (where external means "not-CSS". As of now: TORs).
95 * It makes use of HwvtepUtils class located under ovsdb/hwvtepsouthbound
96 * project for low-level mdsal operations
101 public class ElanL2GatewayUtils {
102 private static final Logger LOG = LoggerFactory.getLogger(ElanL2GatewayUtils.class);
104 private final DataBroker broker;
105 private final ItmRpcService itmRpcService;
106 private final ElanUtils elanUtils;
107 private final EntityOwnershipService entityOwnershipService;
108 private final ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils;
110 private final DataStoreJobCoordinator dataStoreJobCoordinator = DataStoreJobCoordinator.getInstance();
111 private static Timer LogicalSwitchDeleteJobTimer = new Timer();
112 private static final int LOGICAL_SWITCH_DELETE_DELAY = 120000;
113 private final ConcurrentMap<Pair<NodeId, String>, TimerTask> logicalSwitchDeletedTasks = new ConcurrentHashMap<>();
115 public ElanL2GatewayUtils(DataBroker broker, ItmRpcService itmRpcService, ElanUtils elanUtils,
116 EntityOwnershipService entityOwnershipService,
117 ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils) {
118 this.broker = broker;
119 this.itmRpcService = itmRpcService;
120 this.elanUtils = elanUtils;
121 this.entityOwnershipService = entityOwnershipService;
122 this.elanL2GatewayMulticastUtils = elanL2GatewayMulticastUtils;
126 * Installs dpn macs in external device. first it checks if the physical
127 * locator towards this dpn tep is present or not if the physical locator is
128 * present go ahead and add the ucast macs otherwise update the mcast mac
129 * entry to include this dpn tep ip and schedule the job to put ucast macs
130 * once the physical locator is programmed in device
134 * @param lstElanInterfaceNames
135 * the lst Elan interface names
138 * @param externalNodeId
139 * the external node id
141 public void installDpnMacsInL2gwDevice(String elanName, Set<String> lstElanInterfaceNames, BigInteger dpnId,
142 NodeId externalNodeId) {
143 L2GatewayDevice elanL2GwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elanName,
144 externalNodeId.getValue());
145 if (elanL2GwDevice == null) {
146 LOG.debug("L2 gw device not found in elan cache for device name {}", externalNodeId);
149 IpAddress dpnTepIp = getSourceDpnTepIp(dpnId, externalNodeId);
150 if (dpnTepIp == null) {
151 LOG.warn("Could not install dpn macs in l2gw device , dpnTepIp not found dpn : {} , nodeid : {}", dpnId,
156 String logicalSwitchName = getLogicalSwitchFromElan(elanName);
157 RemoteMcastMacs remoteMcastMac = readRemoteMcastMac(externalNodeId, logicalSwitchName,
158 LogicalDatastoreType.OPERATIONAL);
159 boolean phyLocAlreadyExists = checkIfPhyLocatorAlreadyExistsInRemoteMcastEntry(externalNodeId, remoteMcastMac,
161 LOG.debug("phyLocAlreadyExists = {} for locator [{}] in remote mcast entry for elan [{}], nodeId [{}]",
162 phyLocAlreadyExists, String.valueOf(dpnTepIp.getValue()), elanName, externalNodeId.getValue());
163 List<PhysAddress> staticMacs = null;
164 staticMacs = getElanDpnMacsFromInterfaces(lstElanInterfaceNames);
166 if (phyLocAlreadyExists) {
167 scheduleAddDpnMacsInExtDevice(elanName, dpnId, staticMacs, elanL2GwDevice);
170 elanL2GatewayMulticastUtils.scheduleMcastMacUpdateJob(elanName, elanL2GwDevice);
171 scheduleAddDpnMacsInExtDevice(elanName, dpnId, staticMacs, elanL2GwDevice);
175 * gets the macs addresses for elan interfaces
177 * @param lstElanInterfaceNames
178 * the lst elan interface names
181 private List<PhysAddress> getElanDpnMacsFromInterfaces(Set<String> lstElanInterfaceNames) {
182 List<PhysAddress> result = new ArrayList<>();
183 for (String interfaceName : lstElanInterfaceNames) {
184 ElanInterfaceMac elanInterfaceMac = elanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
185 if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
186 for (MacEntry macEntry : elanInterfaceMac.getMacEntry()) {
187 result.add(macEntry.getMacAddress());
195 * Check if phy locator already exists in remote mcast entry.
199 * @param remoteMcastMac
200 * the remote mcast mac
201 * @param expectedPhyLocatorIp
202 * the expected phy locator ip
203 * @return true, if successful
205 public static boolean checkIfPhyLocatorAlreadyExistsInRemoteMcastEntry(NodeId nodeId,
206 RemoteMcastMacs remoteMcastMac, IpAddress expectedPhyLocatorIp) {
207 if (remoteMcastMac != null) {
208 HwvtepPhysicalLocatorAugmentation expectedPhyLocatorAug = HwvtepSouthboundUtils
209 .createHwvtepPhysicalLocatorAugmentation(String.valueOf(expectedPhyLocatorIp.getValue()));
210 HwvtepPhysicalLocatorRef expectedPhyLocRef = new HwvtepPhysicalLocatorRef(
211 HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, expectedPhyLocatorAug));
212 if (remoteMcastMac.getLocatorSet() != null) {
213 for (LocatorSet locatorSet : remoteMcastMac.getLocatorSet()) {
214 if (locatorSet.getLocatorRef().equals(expectedPhyLocRef)) {
215 LOG.trace("matched phyLocRef: {}", expectedPhyLocRef);
225 * Gets the remote mcast mac.
229 * @param logicalSwitchName
230 * the logical switch name
231 * @param datastoreType
233 * @return the remote mcast mac
235 public RemoteMcastMacs readRemoteMcastMac(NodeId nodeId, String logicalSwitchName,
236 LogicalDatastoreType datastoreType) {
237 InstanceIdentifier<LogicalSwitches> logicalSwitch = HwvtepSouthboundUtils
238 .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName));
239 RemoteMcastMacsKey remoteMcastMacsKey = new RemoteMcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch),
240 new MacAddress(ElanConstants.UNKNOWN_DMAC));
241 RemoteMcastMacs remoteMcastMac = HwvtepUtils.getRemoteMcastMac(broker, datastoreType, nodeId,
243 return remoteMcastMac;
247 * Removes the given MAC Addresses from all the External Devices belonging
248 * to the specified ELAN.
250 * @param elanInstance
252 * @param macAddresses
255 public void removeMacsFromElanExternalDevices(ElanInstance elanInstance, List<PhysAddress> macAddresses) {
256 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils
257 .getInvolvedL2GwDevices(elanInstance.getElanInstanceName());
258 for (L2GatewayDevice l2GatewayDevice : elanL2GwDevices.values()) {
259 removeRemoteUcastMacsFromExternalDevice(l2GatewayDevice.getHwvtepNodeId(),
260 elanInstance.getElanInstanceName(), macAddresses);
265 * Removes the given MAC Addresses from the specified External Device.
267 * @param deviceNodeId
269 * @param logicalSwitchName
270 * @param macAddresses
272 * @return the listenable future
274 private ListenableFuture<Void> removeRemoteUcastMacsFromExternalDevice(String deviceNodeId,
275 String logicalSwitchName, List<PhysAddress> macAddresses) {
276 NodeId nodeId = new NodeId(deviceNodeId);
279 List<MacAddress> lstMac = Lists.transform(macAddresses, new Function<PhysAddress, MacAddress>() {
281 public MacAddress apply(PhysAddress physAddress) {
282 return (physAddress != null) ? new MacAddress(physAddress.getValue()) : null;
285 return HwvtepUtils.deleteRemoteUcastMacs(broker, nodeId, logicalSwitchName, lstMac);
288 public ElanInstance getElanInstanceForUcastLocalMac(LocalUcastMacs localUcastMac) {
289 Optional<LogicalSwitches> lsOpc = elanUtils.read(broker, LogicalDatastoreType.OPERATIONAL,
290 (InstanceIdentifier<LogicalSwitches>) localUcastMac.getLogicalSwitchRef().getValue());
291 if (lsOpc.isPresent()) {
292 LogicalSwitches ls = lsOpc.get();
294 // Logical switch name is Elan name
295 String elanName = getElanFromLogicalSwitch(ls.getHwvtepNodeName().getValue());
296 return elanUtils.getElanInstanceByName(elanName);
298 String macAddress = localUcastMac.getMacEntryKey().getValue();
299 LOG.error("Could not find logical_switch for {} being added/deleted", macAddress);
306 * Install external device local macs in dpn.
310 * @param l2gwDeviceNodeId
311 * the l2gw device node id
314 * @param interfaceName
316 public void installL2gwDeviceMacsInDpn(BigInteger dpnId, NodeId l2gwDeviceNodeId, ElanInstance elan,
317 String interfaceName) {
318 L2GatewayDevice l2gwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elan.getElanInstanceName(),
319 l2gwDeviceNodeId.getValue());
320 if (l2gwDevice == null) {
321 LOG.debug("L2 gw device not found in elan cache for device name {}", l2gwDeviceNodeId.getValue());
325 installDmacFlowsOnDpn(dpnId, l2gwDevice, elan, interfaceName);
329 * Install dmac flows on dpn.
337 * @param interfaceName
339 public void installDmacFlowsOnDpn(BigInteger dpnId, L2GatewayDevice l2gwDevice, ElanInstance elan,
340 String interfaceName) {
341 String elanName = elan.getElanInstanceName();
343 List<LocalUcastMacs> l2gwDeviceLocalMacs = l2gwDevice.getUcastLocalMacs();
344 if (l2gwDeviceLocalMacs != null && !l2gwDeviceLocalMacs.isEmpty()) {
345 for (LocalUcastMacs localUcastMac : l2gwDeviceLocalMacs) {
346 // TODO batch these ops
347 elanUtils.installDmacFlowsToExternalRemoteMac(dpnId, l2gwDevice.getHwvtepNodeId(), elan.getElanTag(),
348 elan.getSegmentationId(), localUcastMac.getMacEntryKey().getValue(), elanName, interfaceName);
350 LOG.debug("Installing L2gw device [{}] local macs [size: {}] in dpn [{}] for elan [{}]",
351 l2gwDevice.getHwvtepNodeId(), l2gwDeviceLocalMacs.size(), dpnId, elanName);
356 * Install elan l2gw devices local macs in dpn.
362 * @param interfaceName
364 public void installElanL2gwDevicesLocalMacsInDpn(BigInteger dpnId, ElanInstance elan, String interfaceName) {
365 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevicesFromCache = ElanL2GwCacheUtils
366 .getInvolvedL2GwDevices(elan.getElanInstanceName());
367 if (elanL2GwDevicesFromCache != null) {
368 for (L2GatewayDevice l2gwDevice : elanL2GwDevicesFromCache.values()) {
369 installDmacFlowsOnDpn(dpnId, l2gwDevice, elan, interfaceName);
372 LOG.debug("No Elan l2 gateway devices in cache for [{}] ", elan.getElanInstanceName());
376 public void installL2GwUcastMacInElan(final ElanInstance elan, final L2GatewayDevice extL2GwDevice,
377 final String macToBeAdded, String interfaceName) {
378 final String extDeviceNodeId = extL2GwDevice.getHwvtepNodeId();
379 final String elanInstanceName = elan.getElanInstanceName();
381 // Retrieve all participating DPNs in this Elan. Populate this MAC in
383 // Looping through all DPNs in order to add/remove mac flows in their
385 final List<DpnInterfaces> elanDpns = elanUtils.getInvolvedDpnsInElan(elanInstanceName);
386 if (elanDpns != null && elanDpns.size() > 0) {
387 String jobKey = elan.getElanInstanceName() + ":" + macToBeAdded;
388 ElanClusterUtils.runOnlyInLeaderNode(entityOwnershipService, jobKey, "install l2gw macs in dmac table",
389 new Callable<List<ListenableFuture<Void>>>() {
391 public List<ListenableFuture<Void>> call() throws Exception {
392 List<ListenableFuture<Void>> fts = Lists.newArrayList();
393 if (doesLocalUcastMacExistsInCache(extL2GwDevice, macToBeAdded)) {
394 for (DpnInterfaces elanDpn : elanDpns) {
395 // TODO batch the below call
396 fts.addAll(elanUtils.installDmacFlowsToExternalRemoteMac(elanDpn.getDpId(),
397 extDeviceNodeId, elan.getElanTag(), elan.getSegmentationId(), macToBeAdded,
398 elanInstanceName, interfaceName));
401 LOG.trace("Skipping install of dmac flows for mac {} as it is not found in cache",
408 final IpAddress extL2GwDeviceTepIp = extL2GwDevice.getTunnelIp();
409 final List<PhysAddress> macList = new ArrayList<>();
410 macList.add(new PhysAddress(macToBeAdded));
412 String jobKey = "hwvtep:" + elan.getElanInstanceName() + ":" + macToBeAdded;
413 ElanClusterUtils.runOnlyInLeaderNode(entityOwnershipService, jobKey, "install remote ucast macs in l2gw device",
414 new Callable<List<ListenableFuture<Void>>>() {
416 public List<ListenableFuture<Void>> call() throws Exception {
417 List<ListenableFuture<Void>> fts = Lists.newArrayList();
418 if (!doesLocalUcastMacExistsInCache(extL2GwDevice, macToBeAdded)) {
420 "Skipping install of remote ucast macs {} in l2gw device as it is not found in cache",
424 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils
425 .getInvolvedL2GwDevices(elanInstanceName);
426 for (L2GatewayDevice otherDevice : elanL2GwDevices.values()) {
427 if (!otherDevice.getHwvtepNodeId().equals(extDeviceNodeId)
428 && !areMLAGDevices(extL2GwDevice, otherDevice)) {
429 final String hwvtepId = otherDevice.getHwvtepNodeId();
430 InstanceIdentifier<Node> iid = HwvtepSouthboundUtils
431 .createInstanceIdentifier(new NodeId(hwvtepId));
432 final String logicalSwitchName = elanInstanceName;
434 ListenableFuture<Void> ft = HwvtepUtils.installUcastMacs(broker, hwvtepId, macList,
435 logicalSwitchName, extL2GwDeviceTepIp);
436 // TODO batch the above call
437 Futures.addCallback(ft, new FutureCallback<Void>() {
439 public void onSuccess(Void noarg) {
440 LOG.trace("Successful in initiating ucast_remote_macs addition"
441 + "related to {} in {}", logicalSwitchName, hwvtepId);
445 public void onFailure(Throwable error) {
446 LOG.error(String.format(
447 "Failed adding ucast_remote_macs related to " + "%s in %s",
448 logicalSwitchName, hwvtepId), error);
460 * Does local ucast mac exists in cache.
462 * @param elanL2GwDevice
463 * the elan L2 Gw device
465 * the mac address to be verified
466 * @return true, if successful
468 private static boolean doesLocalUcastMacExistsInCache(L2GatewayDevice elanL2GwDevice, String macAddress) {
469 java.util.Optional<LocalUcastMacs> macExistsInCache = elanL2GwDevice.getUcastLocalMacs().stream()
470 .filter(mac -> mac.getMacEntryKey().getValue().equalsIgnoreCase(macAddress)).findFirst();
471 return macExistsInCache.isPresent();
475 * Un install l2 gw ucast mac from elan.
481 * @param macAddresses
484 public void unInstallL2GwUcastMacFromElan(final ElanInstance elan, final L2GatewayDevice l2GwDevice,
485 final List<MacAddress> macAddresses) {
486 if (macAddresses == null || macAddresses.isEmpty()) {
489 final String elanName = elan.getElanInstanceName();
491 // Retrieve all participating DPNs in this Elan. Populate this MAC in
492 // DMAC table. Looping through all DPNs in order to add/remove mac flows
493 // in their DMAC table
494 for (final MacAddress mac : macAddresses) {
495 final List<DpnInterfaces> elanDpns = elanUtils.getInvolvedDpnsInElan(elanName);
496 if (elanDpns != null && !elanDpns.isEmpty()) {
497 String jobKey = elanName + ":" + mac.getValue();
498 ElanClusterUtils.runOnlyInLeaderNode(entityOwnershipService, jobKey, "delete l2gw macs from dmac table",
499 new Callable<List<ListenableFuture<Void>>>() {
501 public List<ListenableFuture<Void>> call() {
502 List<ListenableFuture<Void>> fts = Lists.newArrayList();
503 for (DpnInterfaces elanDpn : elanDpns) {
504 BigInteger dpnId = elanDpn.getDpId();
505 // never batch deletes
506 fts.addAll(elanUtils.deleteDmacFlowsToExternalMac(elan.getElanTag(), dpnId,
507 l2GwDevice.getHwvtepNodeId(), mac.getValue()));
515 DeleteL2GwDeviceMacsFromElanJob job = new DeleteL2GwDeviceMacsFromElanJob(broker, elanName, l2GwDevice,
517 ElanClusterUtils.runOnlyInLeaderNode(entityOwnershipService, job.getJobKey(), "delete remote ucast macs in l2gw devices", job);
521 * Delete elan l2 gateway devices ucast local macs from dpn.
528 public void deleteElanL2GwDevicesUcastLocalMacsFromDpn(final String elanName, final BigInteger dpnId) {
529 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName);
530 if (elanL2GwDevices == null || elanL2GwDevices.isEmpty()) {
531 LOG.trace("No L2 gateway devices in Elan [{}] cache.", elanName);
534 final ElanInstance elan = elanUtils.getElanInstanceByName(elanName);
536 LOG.error("Could not find Elan by name: {}", elanName);
539 LOG.info("Deleting Elan [{}] L2GatewayDevices UcastLocalMacs from Dpn [{}]", elanName, dpnId);
541 final Long elanTag = elan.getElanTag();
542 for (final L2GatewayDevice l2GwDevice : elanL2GwDevices.values()) {
543 List<MacAddress> localMacs = getL2GwDeviceLocalMacs(l2GwDevice);
544 if (localMacs != null && !localMacs.isEmpty()) {
545 for (final MacAddress mac : localMacs) {
546 String jobKey = elanName + ":" + mac.getValue();
547 ElanClusterUtils.runOnlyInLeaderNode(entityOwnershipService, jobKey, "delete l2gw macs from dmac table",
548 new Callable<List<ListenableFuture<Void>>>() {
550 public List<ListenableFuture<Void>> call() {
551 List<ListenableFuture<Void>> futures = Lists.newArrayList();
553 futures.addAll(elanUtils.deleteDmacFlowsToExternalMac(elanTag, dpnId,
554 l2GwDevice.getHwvtepNodeId(), mac.getValue()));
564 * Gets the l2 gw device local macs.
568 * @return the l2 gw device local macs
570 public static List<MacAddress> getL2GwDeviceLocalMacs(L2GatewayDevice l2gwDevice) {
571 List<MacAddress> macs = new ArrayList<>();
572 if (l2gwDevice == null) {
575 List<LocalUcastMacs> lstUcastLocalMacs = l2gwDevice.getUcastLocalMacs();
576 if (lstUcastLocalMacs != null && !lstUcastLocalMacs.isEmpty()) {
577 macs = Lists.transform(lstUcastLocalMacs, new Function<LocalUcastMacs, MacAddress>() {
579 public MacAddress apply(LocalUcastMacs localUcastMac) {
580 return (localUcastMac != null) ? localUcastMac.getMacEntryKey() : null;
588 * Delete elan macs from L2 gateway device.<br>
589 * This includes deleting ELAN mac table entries plus external device
590 * UcastLocalMacs which are part of the same ELAN.
592 * @param l2GatewayDevice
593 * the l2 gateway device
596 * @return the listenable future
598 public ListenableFuture<Void> deleteElanMacsFromL2GatewayDevice(L2GatewayDevice l2GatewayDevice,
600 String hwvtepNodeId = l2GatewayDevice.getHwvtepNodeId();
601 String logicalSwitch = getLogicalSwitchFromElan(elanName);
603 List<MacAddress> lstElanMacs = getRemoteUcastMacs(new NodeId(hwvtepNodeId), logicalSwitch,
604 LogicalDatastoreType.CONFIGURATION);
605 ListenableFuture<Void> future = HwvtepUtils.deleteRemoteUcastMacs(broker, new NodeId(hwvtepNodeId),
606 logicalSwitch, lstElanMacs);
608 Futures.addCallback(future, new FutureCallback<Void>() {
610 public void onSuccess(Void noarg) {
611 LOG.trace("Successful in batch deletion of elan [{}] macs from l2gw device [{}]", elanName,
616 public void onFailure(Throwable error) {
617 LOG.warn(String.format(
618 "Failed during batch delete of elan [%s] macs from l2gw device [%s]. Retrying with sequential deletes.",
619 elanName, hwvtepNodeId), error);
620 if (lstElanMacs != null && !lstElanMacs.isEmpty()) {
621 for (MacAddress mac : lstElanMacs) {
622 HwvtepUtils.deleteRemoteUcastMac(broker, new NodeId(hwvtepNodeId), logicalSwitch, mac);
628 if (LOG.isDebugEnabled()) {
629 List<String> elanMacs = lstElanMacs.stream().map(mac -> mac.getValue()).collect(Collectors.toList());
630 LOG.debug("Deleting elan [{}] macs from node [{}]. Deleted macs = {}", elanName, hwvtepNodeId, elanMacs);
636 * Gets the remote ucast macs from hwvtep node filtering based on logical
639 * @param hwvtepNodeId
641 * @param logicalSwitch
643 * @param datastoreType
645 * @return the remote ucast macs
647 public List<MacAddress> getRemoteUcastMacs(NodeId hwvtepNodeId, String logicalSwitch,
648 LogicalDatastoreType datastoreType) {
649 List<MacAddress> lstMacs = Collections.emptyList();
650 Node hwvtepNode = HwvtepUtils.getHwVtepNode(broker, datastoreType, hwvtepNodeId);
651 if (hwvtepNode != null) {
652 List<RemoteUcastMacs> remoteUcastMacs = hwvtepNode.getAugmentation(HwvtepGlobalAugmentation.class)
653 .getRemoteUcastMacs();
654 if (remoteUcastMacs != null && !remoteUcastMacs.isEmpty()) {
655 // Filtering remoteUcastMacs based on the logical switch and
656 // forming a list of MacAddress
657 lstMacs = remoteUcastMacs.stream()
658 .filter(mac -> logicalSwitch.equals(mac.getLogicalSwitchRef().getValue()
659 .firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue()))
660 .map(mac -> mac.getMacEntryKey()).collect(Collectors.toList());
667 * Install ELAN macs in L2 Gateway device.<br>
668 * This includes installing ELAN mac table entries plus external device
669 * UcastLocalMacs which are part of the same ELAN.
673 * @param l2GatewayDevice
674 * the l2 gateway device which has to be configured
675 * @return the listenable future
677 public ListenableFuture<Void> installElanMacsInL2GatewayDevice(String elanName,
678 L2GatewayDevice l2GatewayDevice) {
679 String logicalSwitchName = getLogicalSwitchFromElan(elanName);
680 NodeId hwVtepNodeId = new NodeId(l2GatewayDevice.getHwvtepNodeId());
682 List<RemoteUcastMacs> lstL2GatewayDevicesMacs = getOtherDevicesMacs(elanName, l2GatewayDevice, hwVtepNodeId,
684 List<RemoteUcastMacs> lstElanMacTableEntries = getElanMacTableEntriesMacs(elanName, l2GatewayDevice,
685 hwVtepNodeId, logicalSwitchName);
687 List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>(lstL2GatewayDevicesMacs);
688 lstRemoteUcastMacs.addAll(lstElanMacTableEntries);
690 ListenableFuture<Void> future = HwvtepUtils.addRemoteUcastMacs(broker, hwVtepNodeId, lstRemoteUcastMacs);
692 LOG.info("Added RemoteUcastMacs entries [{}] in config DS. NodeID: {}, LogicalSwitch: {}",
693 lstRemoteUcastMacs.size(), hwVtepNodeId.getValue(), logicalSwitchName);
698 * Gets the l2 gateway devices ucast local macs as remote ucast macs.
702 * @param l2GatewayDeviceToBeConfigured
703 * the l2 gateway device to be configured
704 * @param hwVtepNodeId
705 * the hw vtep node Id to be configured
706 * @param logicalSwitchName
707 * the logical switch name
708 * @return the l2 gateway devices macs as remote ucast macs
710 public static List<RemoteUcastMacs> getOtherDevicesMacs(String elanName,
711 L2GatewayDevice l2GatewayDeviceToBeConfigured, NodeId hwVtepNodeId, String logicalSwitchName) {
712 List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>();
713 ConcurrentMap<String, L2GatewayDevice> elanL2GwDevicesFromCache = ElanL2GwCacheUtils
714 .getInvolvedL2GwDevices(elanName);
716 if (elanL2GwDevicesFromCache != null) {
717 for (L2GatewayDevice otherDevice : elanL2GwDevicesFromCache.values()) {
718 if (l2GatewayDeviceToBeConfigured.getHwvtepNodeId().equals(otherDevice.getHwvtepNodeId())) {
721 if (!areMLAGDevices(l2GatewayDeviceToBeConfigured, otherDevice)) {
722 List<LocalUcastMacs> lstUcastLocalMacs = otherDevice.getUcastLocalMacs();
723 if (lstUcastLocalMacs != null) {
724 for (LocalUcastMacs localUcastMac : lstUcastLocalMacs) {
725 HwvtepPhysicalLocatorAugmentation physLocatorAug = HwvtepSouthboundUtils
726 .createHwvtepPhysicalLocatorAugmentation(
727 String.valueOf(otherDevice.getTunnelIp().getValue()));
728 RemoteUcastMacs remoteUcastMac = HwvtepSouthboundUtils.createRemoteUcastMac(hwVtepNodeId,
729 localUcastMac.getMacEntryKey().getValue(), localUcastMac.getIpaddr(),
730 logicalSwitchName, physLocatorAug);
731 lstRemoteUcastMacs.add(remoteUcastMac);
737 return lstRemoteUcastMacs;
743 * @param l2GatewayDevice
744 * the l2 gateway device
745 * @param otherL2GatewayDevice
746 * the other l2 gateway device
747 * @return true, if both the specified l2 gateway devices are part of same
750 public static boolean areMLAGDevices(L2GatewayDevice l2GatewayDevice, L2GatewayDevice otherL2GatewayDevice) {
751 // If tunnel IPs are same, then it is considered to be part of same MLAG
752 return Objects.equals(l2GatewayDevice.getTunnelIp(), otherL2GatewayDevice.getTunnelIp());
756 * Gets the elan mac table entries as remote ucast macs. <br>
757 * Note: ELAN MAC table only contains internal switches MAC's. It doesn't
758 * contain external device MAC's.
762 * @param l2GatewayDeviceToBeConfigured
763 * the l2 gateway device to be configured
764 * @param hwVtepNodeId
765 * the hw vtep node id
766 * @param logicalSwitchName
767 * the logical switch name
768 * @return the elan mac table entries as remote ucast macs
770 public List<RemoteUcastMacs> getElanMacTableEntriesMacs(String elanName,
771 L2GatewayDevice l2GatewayDeviceToBeConfigured, NodeId hwVtepNodeId, String logicalSwitchName) {
772 List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>();
774 MacTable macTable = elanUtils.getElanMacTable(elanName);
775 if (macTable == null || macTable.getMacEntry() == null || macTable.getMacEntry().isEmpty()) {
776 LOG.trace("MacTable is empty for elan: {}", elanName);
777 return lstRemoteUcastMacs;
780 for (MacEntry macEntry : macTable.getMacEntry()) {
781 BigInteger dpnId = elanUtils.getDpidFromInterface(macEntry.getInterface());
783 LOG.error("DPN ID not found for interface {}", macEntry.getInterface());
787 IpAddress dpnTepIp = getSourceDpnTepIp(dpnId, hwVtepNodeId);
788 LOG.trace("Dpn Tep IP: {} for dpnId: {} and nodeId: {}", dpnTepIp, dpnId, hwVtepNodeId.getValue());
789 if (dpnTepIp == null) {
790 LOG.error("TEP IP not found for dpnId {} and nodeId {}", dpnId, hwVtepNodeId.getValue());
793 HwvtepPhysicalLocatorAugmentation physLocatorAug = HwvtepSouthboundUtils
794 .createHwvtepPhysicalLocatorAugmentation(String.valueOf(dpnTepIp.getValue()));
795 // TODO: Query ARP cache to get IP address corresponding to the
797 IpAddress ipAddress = null;
798 RemoteUcastMacs remoteUcastMac = HwvtepSouthboundUtils.createRemoteUcastMac(hwVtepNodeId,
799 macEntry.getMacAddress().getValue(), ipAddress, logicalSwitchName, physLocatorAug);
800 lstRemoteUcastMacs.add(remoteUcastMac);
802 return lstRemoteUcastMacs;
806 * Gets the external tunnel interface name.
812 * @return the external tunnel interface name
814 public String getExternalTunnelInterfaceName(String sourceNode, String dstNode) {
815 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
816 String tunnelInterfaceName = null;
818 Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output = itmRpcService
819 .getExternalTunnelInterfaceName(new GetExternalTunnelInterfaceNameInputBuilder()
820 .setSourceNode(sourceNode).setDestinationNode(dstNode).setTunnelType(tunType).build());
822 RpcResult<GetExternalTunnelInterfaceNameOutput> rpcResult = output.get();
823 if (rpcResult.isSuccessful()) {
824 tunnelInterfaceName = rpcResult.getResult().getInterfaceName();
825 LOG.debug("Tunnel interface name: {} for sourceNode: {} and dstNode: {}", tunnelInterfaceName,
826 sourceNode, dstNode);
828 LOG.warn("RPC call to ITM.GetExternalTunnelInterfaceName failed with error: {}", rpcResult.getErrors());
830 } catch (NullPointerException | InterruptedException | ExecutionException e) {
831 LOG.error("Failed to get external tunnel interface name for sourceNode: {} and dstNode: {}: {} ",
832 sourceNode, dstNode, e);
834 return tunnelInterfaceName;
838 * Gets the source dpn tep ip.
842 * @param dstHwVtepNodeId
843 * the dst hw vtep node id
844 * @return the dpn tep ip
846 public IpAddress getSourceDpnTepIp(BigInteger srcDpnId, NodeId dstHwVtepNodeId) {
847 IpAddress dpnTepIp = null;
848 String tunnelInterfaceName = getExternalTunnelInterfaceName(String.valueOf(srcDpnId),
849 dstHwVtepNodeId.getValue());
850 if (tunnelInterfaceName != null) {
851 Interface tunnelInterface = getInterfaceFromConfigDS(new InterfaceKey(tunnelInterfaceName), broker);
852 if (tunnelInterface != null) {
853 dpnTepIp = tunnelInterface.getAugmentation(IfTunnel.class).getTunnelSource();
855 LOG.warn("Tunnel interface not found for tunnelInterfaceName {}", tunnelInterfaceName);
858 LOG.warn("Tunnel interface name not found for srcDpnId {} and dstHwVtepNodeId {}", srcDpnId,
865 * Update vlan bindings in l2 gateway device.
869 * @param logicalSwitchName
870 * the logical switch name
871 * @param hwVtepDevice
872 * the hardware device
873 * @param defaultVlanId
874 * the default vlan id
875 * @return the listenable future
877 public ListenableFuture<Void> updateVlanBindingsInL2GatewayDevice(NodeId nodeId, String logicalSwitchName,
878 Devices hwVtepDevice, Integer defaultVlanId) {
879 if (hwVtepDevice == null || hwVtepDevice.getInterfaces() == null || hwVtepDevice.getInterfaces().isEmpty()) {
880 String errMsg = "HwVtepDevice is null or interfaces are empty.";
882 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
885 WriteTransaction transaction = broker.newWriteOnlyTransaction();
886 for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice
888 NodeId physicalSwitchNodeId = HwvtepSouthboundUtils.createManagedNodeId(nodeId,
889 hwVtepDevice.getDeviceName());
890 TerminationPoint portTerminationPoint = HwvtepUtils.getPhysicalPortTerminationPoint(broker,
891 LogicalDatastoreType.OPERATIONAL, physicalSwitchNodeId, deviceInterface.getInterfaceName());
892 if (portTerminationPoint == null) {
893 // port is not present in Hwvtep; don't configure VLAN bindings
897 List<VlanBindings> vlanBindings = new ArrayList<>();
898 if (deviceInterface.getSegmentationIds() != null && !deviceInterface.getSegmentationIds().isEmpty()) {
899 for (Integer vlanId : deviceInterface.getSegmentationIds()) {
900 vlanBindings.add(HwvtepSouthboundUtils.createVlanBinding(nodeId, vlanId, logicalSwitchName));
903 // Use defaultVlanId (specified in L2GatewayConnection) if Vlan
904 // ID not specified at interface level.
905 vlanBindings.add(HwvtepSouthboundUtils.createVlanBinding(nodeId, defaultVlanId, logicalSwitchName));
907 HwvtepUtils.mergeVlanBindings(transaction, nodeId, hwVtepDevice.getDeviceName(),
908 deviceInterface.getInterfaceName(), vlanBindings);
910 ListenableFuture<Void> future = transaction.submit();
911 LOG.info("Updated Hwvtep VlanBindings in config DS. NodeID: {}, LogicalSwitch: {}", nodeId.getValue(),
917 * Update vlan bindings in l2 gateway device.
922 * the physical switch name
923 * @param interfaceName
924 * the interface in physical switch
925 * @param vlanBindings
926 * the vlan bindings to be configured
927 * @return the listenable future
929 public ListenableFuture<Void> updateVlanBindingsInL2GatewayDevice(NodeId nodeId, String psName,
930 String interfaceName, List<VlanBindings> vlanBindings) {
931 WriteTransaction transaction = broker.newWriteOnlyTransaction();
932 HwvtepUtils.mergeVlanBindings(transaction, nodeId, psName, interfaceName, vlanBindings);
933 ListenableFuture<Void> future = transaction.submit();
934 LOG.info("Updated Hwvtep VlanBindings in config DS. NodeID: {}", nodeId.getValue());
939 * Delete vlan bindings from l2 gateway device.
943 * @param hwVtepDevice
945 * @param defaultVlanId
946 * the default vlan id
947 * @return the listenable future
949 public ListenableFuture<Void> deleteVlanBindingsFromL2GatewayDevice(NodeId nodeId, Devices hwVtepDevice,
950 Integer defaultVlanId) {
951 if (hwVtepDevice == null || hwVtepDevice.getInterfaces() == null || hwVtepDevice.getInterfaces().isEmpty()) {
952 String errMsg = "HwVtepDevice is null or interfaces are empty.";
954 return Futures.immediateFailedFuture(new RuntimeException(errMsg));
956 NodeId physicalSwitchNodeId = HwvtepSouthboundUtils.createManagedNodeId(nodeId, hwVtepDevice.getDeviceName());
958 WriteTransaction transaction = broker.newWriteOnlyTransaction();
959 for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice
961 String phyPortName = deviceInterface.getInterfaceName();
962 if (deviceInterface.getSegmentationIds() != null && !deviceInterface.getSegmentationIds().isEmpty()) {
963 for (Integer vlanId : deviceInterface.getSegmentationIds()) {
964 HwvtepUtils.deleteVlanBinding(transaction, physicalSwitchNodeId, phyPortName, vlanId);
967 // Use defaultVlanId (specified in L2GatewayConnection) if Vlan
968 // ID not specified at interface level.
969 HwvtepUtils.deleteVlanBinding(transaction, physicalSwitchNodeId, phyPortName, defaultVlanId);
972 ListenableFuture<Void> future = transaction.submit();
974 LOG.info("Deleted Hwvtep VlanBindings from config DS. NodeID: {}, hwVtepDevice: {}, defaultVlanId: {} ",
975 nodeId.getValue(), hwVtepDevice, defaultVlanId);
980 * Gets the elan name from logical switch name.
982 * @param logicalSwitchName
983 * the logical switch name
984 * @return the elan name from logical switch name
986 public static String getElanFromLogicalSwitch(String logicalSwitchName) {
987 // Assuming elan name is same as logical switch name
988 String elanName = logicalSwitchName;
993 * Gets the logical switch name from elan name.
997 * @return the logical switch from elan name
999 public static String getLogicalSwitchFromElan(String elanName) {
1000 // Assuming logical switch name is same as elan name
1001 String logicalSwitchName = elanName;
1002 return logicalSwitchName;
1006 * Gets the l2 gateway connection job key.
1010 * @param logicalSwitchName
1011 * the logical switch name
1012 * @return the l2 gateway connection job key
1014 public static String getL2GatewayConnectionJobKey(String nodeId, String logicalSwitchName) {
1015 return logicalSwitchName;
1018 public static InstanceIdentifier<Interface> getInterfaceIdentifier(InterfaceKey interfaceKey) {
1019 InstanceIdentifier.InstanceIdentifierBuilder<Interface> interfaceInstanceIdentifierBuilder = InstanceIdentifier
1020 .builder(Interfaces.class).child(Interface.class, interfaceKey);
1021 return interfaceInstanceIdentifierBuilder.build();
1024 public static Interface getInterfaceFromConfigDS(InterfaceKey interfaceKey, DataBroker dataBroker) {
1025 InstanceIdentifier<Interface> interfaceId = getInterfaceIdentifier(interfaceKey);
1026 Optional<Interface> interfaceOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION, interfaceId,
1028 if (!interfaceOptional.isPresent()) {
1032 return interfaceOptional.get();
1036 * Delete l2 gateway device ucast local macs from elan.<br>
1037 * Deletes macs from internal ELAN nodes and also on rest of external l2
1038 * gateway devices which are part of the ELAN.
1040 * @param l2GatewayDevice
1041 * the l2 gateway device whose ucast local macs to be deleted
1045 * @return the listenable future
1047 public List<ListenableFuture<Void>> deleteL2GwDeviceUcastLocalMacsFromElan(L2GatewayDevice l2GatewayDevice,
1049 LOG.info("Deleting L2GatewayDevice [{}] UcastLocalMacs from elan [{}]", l2GatewayDevice.getHwvtepNodeId(),
1052 List<ListenableFuture<Void>> futures = new ArrayList<>();
1053 ElanInstance elan = elanUtils.getElanInstanceByName(elanName);
1055 LOG.error("Could not find Elan by name: {}", elanName);
1059 List<MacAddress> localMacs = getL2GwDeviceLocalMacs(l2GatewayDevice);
1060 unInstallL2GwUcastMacFromElan(elan, l2GatewayDevice, localMacs);
1064 public static void createItmTunnels(ItmRpcService itmRpcService, String hwvtepId, String psName,
1065 IpAddress tunnelIp) {
1066 AddL2GwDeviceInputBuilder builder = new AddL2GwDeviceInputBuilder();
1067 builder.setTopologyId(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID.getValue());
1068 builder.setNodeId(HwvtepSouthboundUtils.createManagedNodeId(new NodeId(hwvtepId), psName).getValue());
1069 builder.setIpAddress(tunnelIp);
1071 Future<RpcResult<Void>> result = itmRpcService.addL2GwDevice(builder.build());
1072 RpcResult<Void> rpcResult = result.get();
1073 if (rpcResult.isSuccessful()) {
1074 LOG.info("Created ITM tunnels for {}", hwvtepId);
1076 LOG.error("Failed to create ITM Tunnels: ", rpcResult.getErrors());
1078 } catch (InterruptedException | ExecutionException e) {
1079 LOG.error("RPC to create ITM tunnels failed", e);
1083 public static String getNodeIdFromDpnId(BigInteger dpnId) {
1084 return MDSALUtil.NODE_PREFIX + MDSALUtil.SEPARATOR + dpnId.toString();
1087 public void scheduleAddDpnMacInExtDevices(String elanName, BigInteger dpId,
1088 List<PhysAddress> staticMacAddresses) {
1089 ConcurrentMap<String, L2GatewayDevice> elanDevices = ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName);
1090 for (final L2GatewayDevice externalDevice : elanDevices.values()) {
1091 scheduleAddDpnMacsInExtDevice(elanName, dpId, staticMacAddresses, externalDevice);
1095 public void scheduleAddDpnMacsInExtDevice(final String elanName, BigInteger dpId,
1096 final List<PhysAddress> staticMacAddresses, final L2GatewayDevice externalDevice) {
1097 NodeId nodeId = new NodeId(externalDevice.getHwvtepNodeId());
1098 final IpAddress dpnTepIp = getSourceDpnTepIp(dpId, nodeId);
1099 LOG.trace("Dpn Tep IP: {} for dpnId: {} and nodeId: {}", dpnTepIp, dpId, nodeId);
1100 if (dpnTepIp == null) {
1101 LOG.error("could not install dpn mac in l2gw TEP IP not found for dpnId {} and nodeId {}", dpId, nodeId);
1104 TerminationPointKey tpKey = HwvtepSouthboundUtils.getTerminationPointKey(dpnTepIp.getIpv4Address().getValue());
1105 InstanceIdentifier<TerminationPoint> tpPath = HwvtepSouthboundUtils.createTerminationPointId(nodeId, tpKey);
1107 HwvtepTerminationPointListener.runJobAfterPhysicalLocatorIsAvialable(tpPath, new Runnable() {
1110 HwvtepUtils.installUcastMacs(broker, externalDevice.getHwvtepNodeId(), staticMacAddresses, elanName,
1116 public void scheduleDeleteLogicalSwitch(final NodeId hwvtepNodeId, final String lsName) {
1117 TimerTask logicalSwitchDeleteTask = new TimerTask() {
1120 Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<NodeId, String>(hwvtepNodeId,
1122 logicalSwitchDeletedTasks.remove(nodeIdLogicalSwitchNamePair);
1124 DeleteLogicalSwitchJob deleteLsJob = new DeleteLogicalSwitchJob(broker, hwvtepNodeId, lsName);
1125 dataStoreJobCoordinator.enqueueJob(deleteLsJob.getJobKey(), deleteLsJob,
1126 SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
1129 Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<>(hwvtepNodeId, lsName);
1130 logicalSwitchDeletedTasks.put(nodeIdLogicalSwitchNamePair, logicalSwitchDeleteTask);
1131 LogicalSwitchDeleteJobTimer.schedule(logicalSwitchDeleteTask, LOGICAL_SWITCH_DELETE_DELAY);
1134 public void cancelDeleteLogicalSwitch(final NodeId hwvtepNodeId, final String lsName) {
1135 Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<>(hwvtepNodeId, lsName);
1136 TimerTask logicalSwitchDeleteTask = logicalSwitchDeletedTasks.get(nodeIdLogicalSwitchNamePair);
1137 if (logicalSwitchDeleteTask != null) {
1138 LOG.debug("Delete logical switch {} action on node {} cancelled", lsName, hwvtepNodeId);
1139 logicalSwitchDeleteTask.cancel();
1140 logicalSwitchDeletedTasks.remove(nodeIdLogicalSwitchNamePair);