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 static java.util.Collections.emptyList;
11 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12 import static org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlanNetworkOrVxlanSegment;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.Collection;
19 import java.util.List;
20 import java.util.Objects;
21 import javax.inject.Inject;
22 import javax.inject.Singleton;
23 import org.eclipse.jdt.annotation.NonNull;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
28 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
29 import org.opendaylight.genius.infra.Datastore;
30 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
31 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
32 import org.opendaylight.genius.infra.TypedWriteTransaction;
33 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
34 import org.opendaylight.genius.mdsalutil.MDSALUtil;
35 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
36 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
37 import org.opendaylight.genius.utils.batching.ResourceBatchingManager;
38 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
39 import org.opendaylight.genius.utils.hwvtep.HwvtepUtils;
40 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
41 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
42 import org.opendaylight.netvirt.elan.l2gw.jobs.HwvtepDeviceMcastMacUpdateJob;
43 import org.opendaylight.netvirt.elan.l2gw.jobs.McastUpdateJob;
44 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
45 import org.opendaylight.netvirt.elan.utils.ElanConstants;
46 import org.opendaylight.netvirt.elan.utils.ElanItmUtils;
47 import org.opendaylight.netvirt.elan.utils.ElanUtils;
48 import org.opendaylight.netvirt.elan.utils.Scheduler;
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.yang.types.rev130715.MacAddress;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.DesignatedSwitchesForExternalTunnels;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnel;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnelKey;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstance;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTeps;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTepsBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTepsKey;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSetBuilder;
79 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
80 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
81 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
82 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
83 import org.slf4j.Logger;
84 import org.slf4j.LoggerFactory;
87 * The utility class to handle ELAN L2 Gateway related to multicast.
90 public class ElanL2GatewayMulticastUtils {
92 /** The Constant LOG. */
93 private static final Logger LOG = LoggerFactory.getLogger(ElanL2GatewayMulticastUtils.class);
96 private final DataBroker broker;
97 private final ManagedNewTransactionRunner txRunner;
99 private final ElanItmUtils elanItmUtils;
100 private final JobCoordinator jobCoordinator;
101 private final ElanUtils elanUtils;
102 private final IMdsalApiManager mdsalManager;
103 private final IInterfaceManager interfaceManager;
104 private final ElanClusterUtils elanClusterUtils;
105 private final Scheduler scheduler;
108 public ElanL2GatewayMulticastUtils(DataBroker broker, ElanItmUtils elanItmUtils, JobCoordinator jobCoordinator,
109 ElanUtils elanUtils, IMdsalApiManager mdsalManager,
110 IInterfaceManager interfaceManager, ElanClusterUtils elanClusterUtils,
111 Scheduler scheduler) {
112 this.broker = broker;
113 this.txRunner = new ManagedNewTransactionRunnerImpl(broker);
114 this.elanItmUtils = elanItmUtils;
115 this.jobCoordinator = jobCoordinator;
116 this.elanUtils = elanUtils;
117 this.mdsalManager = mdsalManager;
118 this.interfaceManager = interfaceManager;
119 this.elanClusterUtils = elanClusterUtils;
120 this.scheduler = scheduler;
124 * Handle mcast for elan l2 gw device add.
125 * @param elanName the elan name
126 * @param device the device
128 public void handleMcastForElanL2GwDeviceAdd(String elanName, L2GatewayDevice device) {
129 InstanceIdentifier<ExternalTeps> tepPath = buildExternalTepPath(elanName, device.getTunnelIp());
130 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
131 tx -> tx.put(tepPath, buildExternalTeps(device))), LOG, "Failed to write to config external tep {}",
133 updateMcastMacsForAllElanDevices(elanName, device, true/* updateThisDevice */);
136 public static InstanceIdentifier<ExternalTeps> buildExternalTepPath(String elan, IpAddress tepIp) {
137 return InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, new ElanInstanceKey(elan))
138 .child(ExternalTeps.class, new ExternalTepsKey(tepIp)).build();
141 protected ExternalTeps buildExternalTeps(L2GatewayDevice device) {
142 return new ExternalTepsBuilder().setTepIp(device.getTunnelIp()).setNodeid(device.getHwvtepNodeId()).build();
146 * Updates the remote mcast mac table for all the devices in this elan
147 * includes all the dpn tep ips and other devices tep ips in broadcast
151 * the elan to be updated
153 public void updateRemoteMcastMacOnElanL2GwDevices(String elanName) {
154 for (L2GatewayDevice device : ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName)) {
155 prepareRemoteMcastMacUpdateOnDevice(elanName, device);
159 public void scheduleMcastMacUpdateJob(String elanName, L2GatewayDevice device) {
160 HwvtepDeviceMcastMacUpdateJob job = new HwvtepDeviceMcastMacUpdateJob(this, elanName,device);
161 jobCoordinator.enqueueJob(job.getJobKey(), job);
165 * Update remote mcast mac on elan l2 gw device.
172 public void updateRemoteMcastMacOnElanL2GwDevice(String elanName, L2GatewayDevice device) {
173 prepareRemoteMcastMacUpdateOnDevice(elanName, device);
176 public ListenableFuture<Void> prepareRemoteMcastMacUpdateOnDevice(String elanName, L2GatewayDevice device) {
177 Collection<L2GatewayDevice> elanL2gwDevices = ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName);
178 List<DpnInterfaces> dpns = elanUtils.getElanDPNByName(elanName);
179 List<IpAddress> dpnsTepIps = getAllTepIpsOfDpns(device, dpns);
180 List<IpAddress> l2GwDevicesTepIps = getAllTepIpsOfL2GwDevices(elanL2gwDevices);
181 return prepareRemoteMcastMacEntry(elanName, device, dpnsTepIps, l2GwDevicesTepIps);
185 * Update mcast macs for this elan.
186 * for all dpns in this elan recompute and update broadcast group
187 * for all l2gw devices in this elan recompute and update remote mcast mac entry
193 * @param updateThisDevice
194 * the update this device
196 public void updateMcastMacsForAllElanDevices(String elanName, L2GatewayDevice device,
197 boolean updateThisDevice) {
198 if (updateThisDevice) {
199 McastUpdateJob.updateAllMcastsForConnectionAdd(elanName, this, elanClusterUtils);
201 McastUpdateJob.updateAllMcastsForConnectionDelete(elanName, this, elanClusterUtils, device);
205 public void updateRemoteBroadcastGroupForAllElanDpns(ElanInstance elanInfo,
206 TypedWriteTransaction<Datastore.Configuration> confTx) {
207 List<DpnInterfaces> dpns = elanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName());
208 for (DpnInterfaces dpn : dpns) {
209 setupElanBroadcastGroups(elanInfo, dpn.getDpId(), confTx);
213 public void setupElanBroadcastGroups(ElanInstance elanInfo, BigInteger dpnId,
214 TypedWriteTransaction<Datastore.Configuration> confTx) {
215 setupElanBroadcastGroups(elanInfo, null, dpnId, confTx);
218 public void setupElanBroadcastGroups(ElanInstance elanInfo, @Nullable DpnInterfaces dpnInterfaces, BigInteger dpnId,
219 TypedWriteTransaction<Datastore.Configuration> confTx) {
220 setupStandardElanBroadcastGroups(elanInfo, dpnInterfaces, dpnId, confTx);
221 setupLeavesEtreeBroadcastGroups(elanInfo, dpnInterfaces, dpnId, confTx);
224 public void setupStandardElanBroadcastGroups(ElanInstance elanInfo, @Nullable DpnInterfaces dpnInterfaces,
225 BigInteger dpnId, TypedWriteTransaction<Datastore.Configuration> confTx) {
226 List<Bucket> listBucket = new ArrayList<>();
229 Long elanTag = elanInfo.getElanTag();
230 List<Action> listAction = new ArrayList<>();
231 listAction.add(new ActionGroup(ElanUtils.getElanLocalBCGId(elanTag)).buildAction(++actionKey));
232 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
233 MDSALUtil.WATCH_GROUP));
235 List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId, elanTag);
236 listBucket.addAll(listBucketInfoRemote);
237 long groupId = ElanUtils.getElanRemoteBCGId(elanTag);
238 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
239 MDSALUtil.buildBucketLists(listBucket));
240 LOG.trace("Installing the remote BroadCast Group:{}", group);
241 mdsalManager.addGroup(confTx, dpnId, group);
244 public void setupLeavesEtreeBroadcastGroups(ElanInstance elanInfo, @Nullable DpnInterfaces dpnInterfaces,
245 BigInteger dpnId, TypedWriteTransaction<Datastore.Configuration> confTx) {
246 EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class);
247 if (etreeInstance != null) {
248 long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue();
249 List<Bucket> listBucket = new ArrayList<>();
252 List<Action> listAction = new ArrayList<>();
253 listAction.add(new ActionGroup(ElanUtils.getEtreeLeafLocalBCGId(etreeLeafTag)).buildAction(++actionKey));
254 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
255 MDSALUtil.WATCH_GROUP));
257 List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId,
259 listBucket.addAll(listBucketInfoRemote);
260 long groupId = ElanUtils.getEtreeLeafRemoteBCGId(etreeLeafTag);
261 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
262 MDSALUtil.buildBucketLists(listBucket));
263 LOG.trace("Installing the remote BroadCast Group:{}", group);
264 mdsalManager.addGroup(confTx, dpnId, group);
269 private static DpnInterfaces getDpnInterfaces(ElanDpnInterfacesList elanDpns, BigInteger dpnId) {
270 if (elanDpns != null) {
271 for (DpnInterfaces dpnInterface : elanDpns.nonnullDpnInterfaces()) {
272 if (Objects.equals(dpnInterface.getDpId(), dpnId)) {
280 private List<Bucket> getRemoteBCGroupExternalPortBuckets(ElanDpnInterfacesList elanDpns,
281 DpnInterfaces dpnInterfaces, BigInteger dpnId, int bucketId) {
282 DpnInterfaces currDpnInterfaces = dpnInterfaces != null ? dpnInterfaces : getDpnInterfaces(elanDpns, dpnId);
283 if (currDpnInterfaces == null || !elanUtils.isDpnPresent(currDpnInterfaces.getDpId())
284 || currDpnInterfaces.getInterfaces() == null || currDpnInterfaces.getInterfaces().isEmpty()) {
287 List<Bucket> listBucketInfo = new ArrayList<>();
288 for (String interfaceName : currDpnInterfaces.getInterfaces()) {
289 if (interfaceManager.isExternalInterface(interfaceName)) {
290 List<Action> listActionInfo = elanItmUtils.getExternalPortItmEgressAction(interfaceName);
291 if (!listActionInfo.isEmpty()) {
292 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
293 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
298 return listBucketInfo;
302 public List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo, @Nullable DpnInterfaces dpnInterfaces,
303 BigInteger dpnId, int bucketId, long elanTag) {
304 List<Bucket> listBucketInfo = new ArrayList<>();
305 ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
307 if (isVxlanNetworkOrVxlanSegment(elanInfo)) {
308 listBucketInfo.addAll(getRemoteBCGroupTunnelBuckets(elanDpns, dpnId, bucketId,
309 elanUtils.isOpenstackVniSemanticsEnforced()
310 ? ElanUtils.getVxlanSegmentationId(elanInfo) : elanTag));
312 listBucketInfo.addAll(getRemoteBCGroupExternalPortBuckets(elanDpns, dpnInterfaces, dpnId,
313 getNextAvailableBucketId(listBucketInfo.size())));
314 listBucketInfo.addAll(getRemoteBCGroupBucketsOfElanExternalTeps(elanInfo, dpnId,
315 getNextAvailableBucketId(listBucketInfo.size())));
316 return listBucketInfo;
319 public List<Bucket> getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, BigInteger dpnId,
321 List<Bucket> listBucketInfo = new ArrayList<>();
322 for (L2GatewayDevice device : ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanInfo.getElanInstanceName())) {
323 String interfaceName = elanItmUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
324 device.getHwvtepNodeId());
325 if (interfaceName == null) {
328 List<Action> listActionInfo = elanItmUtils.buildTunnelItmEgressActions(interfaceName,
329 ElanUtils.getVxlanSegmentationId(elanInfo), true);
330 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
331 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
334 return listBucketInfo;
337 public List<Bucket> getRemoteBCGroupBucketsOfElanExternalTeps(ElanInstance elanInfo, BigInteger dpnId,
339 ElanInstance operElanInstance = null;
341 operElanInstance = new SingleTransactionDataBroker(broker).syncReadOptional(
342 LogicalDatastoreType.OPERATIONAL,
343 InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, elanInfo.key())
345 } catch (ReadFailedException e) {
346 LOG.error("Failed to read elan instance operational path {}", elanInfo, e);
349 if (operElanInstance == null) {
352 List<ExternalTeps> teps = operElanInstance.getExternalTeps();
353 if (teps == null || teps.isEmpty()) {
356 List<Bucket> listBucketInfo = new ArrayList<>();
357 for (ExternalTeps tep : teps) {
358 String externalTep = tep.getNodeid() != null ? tep.getNodeid() : tep.getTepIp().toString();
359 String interfaceName = elanItmUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
361 if (interfaceName == null) {
362 LOG.error("Could not get interface name to ext tunnel {} {}", dpnId, tep.getTepIp());
365 List<Action> listActionInfo = elanItmUtils.buildTunnelItmEgressActions(interfaceName,
366 ElanUtils.getVxlanSegmentationId(elanInfo), false);
367 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
368 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
371 return listBucketInfo;
374 private static int getNextAvailableBucketId(int bucketSize) {
375 return bucketSize + 1;
378 @SuppressWarnings("checkstyle:IllegalCatch")
379 private List<Bucket> getRemoteBCGroupTunnelBuckets(ElanDpnInterfacesList elanDpns, BigInteger dpnId, int bucketId,
381 List<Bucket> listBucketInfo = new ArrayList<>();
382 if (elanDpns != null) {
383 for (DpnInterfaces dpnInterface : elanDpns.nonnullDpnInterfaces()) {
384 if (!Objects.equals(dpnInterface.getDpId(), dpnId) && dpnInterface.getInterfaces() != null
385 && !dpnInterface.getInterfaces().isEmpty()) {
387 List<Action> listActionInfo = elanItmUtils.getInternalTunnelItmEgressAction(dpnId,
388 dpnInterface.getDpId(), elanTagOrVni);
389 if (listActionInfo.isEmpty()) {
392 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
393 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
395 } catch (Exception ex) {
396 LOG.error("Logical Group Interface not found between source Dpn - {}, destination Dpn - {} ",
397 dpnId, dpnInterface.getDpId(), ex);
402 return listBucketInfo;
406 * Update remote mcast mac.
414 * @param l2GwDevicesTepIps
415 * the l2 gw devices tep ips
416 * @return the write transaction
418 private ListenableFuture<Void> prepareRemoteMcastMacEntry(String elanName,
419 L2GatewayDevice device, List<IpAddress> dpnsTepIps,
420 List<IpAddress> l2GwDevicesTepIps) {
421 NodeId nodeId = new NodeId(device.getHwvtepNodeId());
423 ArrayList<IpAddress> remoteTepIps = new ArrayList<>(l2GwDevicesTepIps);
424 remoteTepIps.remove(device.getTunnelIp());
425 remoteTepIps.addAll(dpnsTepIps);
426 IpAddress dhcpDesignatedSwitchTepIp = getTepIpOfDesignatedSwitchForExternalTunnel(device, elanName);
427 if (dpnsTepIps.isEmpty()) {
428 // If no dpns in elan, configure dhcp designated switch Tep Ip as a
429 // physical locator in l2 gw device
430 if (dhcpDesignatedSwitchTepIp != null) {
431 remoteTepIps.add(dhcpDesignatedSwitchTepIp);
433 HwvtepPhysicalLocatorAugmentation phyLocatorAug = HwvtepSouthboundUtils
434 .createHwvtepPhysicalLocatorAugmentation(dhcpDesignatedSwitchTepIp);
435 InstanceIdentifier<TerminationPoint> iid =
436 HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, phyLocatorAug);
437 TerminationPoint terminationPoint = new TerminationPointBuilder()
438 .withKey(HwvtepSouthboundUtils.getTerminationPointKey(phyLocatorAug))
439 .addAugmentation(HwvtepPhysicalLocatorAugmentation.class, phyLocatorAug).build();
440 ResourceBatchingManager.getInstance().put(ResourceBatchingManager.ShardResource.CONFIG_TOPOLOGY,
441 iid, terminationPoint);
442 LOG.info("Adding PhysicalLocator for node: {} with Dhcp designated switch Tep Ip {} "
443 + "as physical locator, elan {}", device.getHwvtepNodeId(),
444 dhcpDesignatedSwitchTepIp.stringValue(), elanName);
446 LOG.warn("Dhcp designated switch Tep Ip not found for l2 gw node {} and elan {}",
447 device.getHwvtepNodeId(), elanName);
450 if (dhcpDesignatedSwitchTepIp != null && !remoteTepIps.contains(dhcpDesignatedSwitchTepIp)) {
451 remoteTepIps.add(dhcpDesignatedSwitchTepIp);
453 String logicalSwitchName = ElanL2GatewayUtils.getLogicalSwitchFromElan(elanName);
454 LOG.info("Adding RemoteMcastMac for node: {} with physical locators: {}", device.getHwvtepNodeId(),
456 return putRemoteMcastMac(nodeId, logicalSwitchName, remoteTepIps);
460 * Put remote mcast mac in config DS.
464 * @param logicalSwitchName
465 * the logical switch name
469 private static ListenableFuture<Void> putRemoteMcastMac(NodeId nodeId, String logicalSwitchName,
470 ArrayList<IpAddress> tepIps) {
471 List<LocatorSet> locators = new ArrayList<>();
472 for (IpAddress tepIp : tepIps) {
473 HwvtepPhysicalLocatorAugmentation phyLocatorAug = HwvtepSouthboundUtils
474 .createHwvtepPhysicalLocatorAugmentation(tepIp);
475 HwvtepPhysicalLocatorRef phyLocRef = new HwvtepPhysicalLocatorRef(
476 HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, phyLocatorAug));
477 locators.add(new LocatorSetBuilder().setLocatorRef(phyLocRef).build());
480 HwvtepLogicalSwitchRef lsRef = new HwvtepLogicalSwitchRef(HwvtepSouthboundUtils
481 .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName)));
482 RemoteMcastMacs remoteMcastMac = new RemoteMcastMacsBuilder()
483 .setMacEntryKey(new MacAddress(ElanConstants.UNKNOWN_DMAC)).setLogicalSwitchRef(lsRef)
484 .setLocatorSet(locators).build();
485 InstanceIdentifier<RemoteMcastMacs> iid = HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId,
486 remoteMcastMac.key());
487 return ResourceBatchingManager.getInstance().put(ResourceBatchingManager.ShardResource.CONFIG_TOPOLOGY,
488 iid, remoteMcastMac);
493 * Gets all the tep ips of dpns.
499 * @return the all tep ips of dpns and devices
501 private List<IpAddress> getAllTepIpsOfDpns(L2GatewayDevice l2GwDevice, List<DpnInterfaces> dpns) {
502 List<IpAddress> tepIps = new ArrayList<>();
503 for (DpnInterfaces dpn : dpns) {
504 IpAddress internalTunnelIp = elanItmUtils.getSourceDpnTepIp(dpn.getDpId(),
505 new NodeId(l2GwDevice.getHwvtepNodeId()));
506 if (internalTunnelIp != null) {
507 tepIps.add(internalTunnelIp);
514 * Gets the all tep ips of l2 gw devices.
518 * @return the all tep ips of l2 gw devices
520 private static List<IpAddress> getAllTepIpsOfL2GwDevices(Collection<L2GatewayDevice> devices) {
521 List<IpAddress> tepIps = new ArrayList<>();
522 for (L2GatewayDevice otherDevice : devices) {
523 // There is no need to add the same tep ip to the list.
524 if (!tepIps.contains(otherDevice.getTunnelIp())) {
525 tepIps.add(otherDevice.getTunnelIp());
532 * Handle mcast for elan l2 gw device delete.
535 * the elan instance name
536 * @param l2GatewayDevice
537 * the l2 gateway device
538 * @return the listenable future
540 public List<ListenableFuture<Void>> handleMcastForElanL2GwDeviceDelete(String elanName,
541 L2GatewayDevice l2GatewayDevice) {
542 ListenableFuture<Void> deleteTepFuture =
543 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
544 tx -> tx.delete(buildExternalTepPath(elanName, l2GatewayDevice.getTunnelIp())));
545 updateMcastMacsForAllElanDevices(elanName, l2GatewayDevice, false/* updateThisDevice */);
546 ListenableFuture<Void> deleteRemoteMcastMacFuture = deleteRemoteMcastMac(
547 new NodeId(l2GatewayDevice.getHwvtepNodeId()), elanName);
548 return Arrays.asList(deleteRemoteMcastMacFuture, deleteTepFuture);
552 * Delete remote mcast mac from Hwvtep node.
556 * @param logicalSwitchName
557 * the logical switch name
558 * @return the listenable future
560 public ListenableFuture<Void> deleteRemoteMcastMac(NodeId nodeId, String logicalSwitchName) {
561 InstanceIdentifier<LogicalSwitches> logicalSwitch = HwvtepSouthboundUtils
562 .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName));
563 RemoteMcastMacsKey remoteMcastMacsKey = new RemoteMcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch),
564 new MacAddress(ElanConstants.UNKNOWN_DMAC));
566 LOG.info("Deleting RemoteMcastMacs entry on node: {} for logical switch: {}", nodeId.getValue(),
568 return HwvtepUtils.deleteRemoteMcastMac(broker, nodeId, remoteMcastMacsKey);
572 * Gets the tep ip of designated switch for external tunnel.
576 * @param elanInstanceName
577 * the elan instance name
578 * @return the tep ip of designated switch for external tunnel
580 public IpAddress getTepIpOfDesignatedSwitchForExternalTunnel(L2GatewayDevice l2GwDevice,
581 String elanInstanceName) {
582 IpAddress tepIp = null;
583 if (l2GwDevice.getTunnelIp() == null) {
584 LOG.warn("Tunnel IP not found for {}", l2GwDevice.getDeviceName());
587 DesignatedSwitchForTunnel desgSwitch = getDesignatedSwitchForExternalTunnel(l2GwDevice.getTunnelIp(),
589 if (desgSwitch != null) {
590 tepIp = elanItmUtils.getSourceDpnTepIp(BigInteger.valueOf(desgSwitch.getDpId()),
591 new NodeId(l2GwDevice.getHwvtepNodeId()));
597 * Gets the designated switch for external tunnel.
601 * @param elanInstanceName
602 * the elan instance name
603 * @return the designated switch for external tunnel
605 public DesignatedSwitchForTunnel getDesignatedSwitchForExternalTunnel(IpAddress tunnelIp,
606 String elanInstanceName) {
607 InstanceIdentifier<DesignatedSwitchForTunnel> instanceIdentifier = InstanceIdentifier
608 .builder(DesignatedSwitchesForExternalTunnels.class)
609 .child(DesignatedSwitchForTunnel.class, new DesignatedSwitchForTunnelKey(elanInstanceName, tunnelIp))
611 return MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, instanceIdentifier).orNull();