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 org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlan;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.SettableFuture;
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.Objects;
21 import java.util.concurrent.ConcurrentMap;
22 import javax.annotation.Nonnull;
23 import javax.inject.Inject;
24 import javax.inject.Singleton;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
29 import org.opendaylight.genius.mdsalutil.MDSALUtil;
30 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
31 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
32 import org.opendaylight.genius.utils.batching.ResourceBatchingManager;
33 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
34 import org.opendaylight.genius.utils.hwvtep.HwvtepUtils;
35 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
36 import org.opendaylight.netvirt.elan.l2gw.jobs.HwvtepDeviceMcastMacUpdateJob;
37 import org.opendaylight.netvirt.elan.utils.ElanConstants;
38 import org.opendaylight.netvirt.elan.utils.ElanItmUtils;
39 import org.opendaylight.netvirt.elan.utils.ElanUtils;
40 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
41 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.DesignatedSwitchesForExternalTunnels;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnel;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnelKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstance;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTeps;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSetBuilder;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
67 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
68 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
69 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
70 import org.slf4j.Logger;
71 import org.slf4j.LoggerFactory;
74 * The utility class to handle ELAN L2 Gateway related to multicast.
77 public class ElanL2GatewayMulticastUtils {
79 /** The Constant LOG. */
80 private static final Logger LOG = LoggerFactory.getLogger(ElanL2GatewayMulticastUtils.class);
83 private final DataBroker broker;
85 private final ElanItmUtils elanItmUtils;
86 private final JobCoordinator jobCoordinator;
87 private final ElanUtils elanUtils;
88 private final IMdsalApiManager mdsalManager;
89 private final IInterfaceManager interfaceManager;
92 public ElanL2GatewayMulticastUtils(DataBroker broker, ElanItmUtils elanItmUtils, JobCoordinator jobCoordinator,
93 ElanUtils elanUtils, IMdsalApiManager mdsalManager, IInterfaceManager interfaceManager) {
95 this.elanItmUtils = elanItmUtils;
96 this.jobCoordinator = jobCoordinator;
97 this.elanUtils = elanUtils;
98 this.mdsalManager = mdsalManager;
99 this.interfaceManager = interfaceManager;
103 * Handle mcast for elan l2 gw device add.
109 * @return the listenable future
111 public ListenableFuture<Void> handleMcastForElanL2GwDeviceAdd(String elanName, ElanInstance elanInstance,
112 L2GatewayDevice device) {
113 return updateMcastMacsForAllElanDevices(elanName, elanInstance, device, true/* updateThisDevice */);
117 * Updates the remote mcast mac table for all the devices in this elan
118 * includes all the dpn tep ips and other devices tep ips in broadcast
122 * the elan to be updated
123 * @return the listenable future
125 @SuppressWarnings("checkstyle:IllegalCatch")
126 public ListenableFuture<Void> updateRemoteMcastMacOnElanL2GwDevices(String elanName) {
128 WriteTransaction transaction = broker.newWriteOnlyTransaction();
129 for (L2GatewayDevice device : ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName).values()) {
130 prepareRemoteMcastMacUpdateOnDevice(transaction, elanName, device);
132 return transaction.submit();
133 } catch (RuntimeException e) {
134 LOG.error("Failed to configure mcast mac on elan " + elanName, e);
135 return Futures.immediateFailedCheckedFuture(e);
139 public void scheduleMcastMacUpdateJob(String elanName, L2GatewayDevice device) {
140 HwvtepDeviceMcastMacUpdateJob job = new HwvtepDeviceMcastMacUpdateJob(this, elanName,device);
141 jobCoordinator.enqueueJob(job.getJobKey(), job);
145 * Update remote mcast mac on elan l2 gw device.
151 * @return the listenable future
153 public ListenableFuture<Void> updateRemoteMcastMacOnElanL2GwDevice(String elanName, L2GatewayDevice device) {
154 WriteTransaction transaction = broker.newWriteOnlyTransaction();
155 prepareRemoteMcastMacUpdateOnDevice(transaction, elanName, device);
156 return transaction.submit();
159 public void prepareRemoteMcastMacUpdateOnDevice(WriteTransaction transaction,String elanName,
160 L2GatewayDevice device) {
161 ConcurrentMap<String, L2GatewayDevice> elanL2gwDevices = ElanL2GwCacheUtils
162 .getInvolvedL2GwDevices(elanName);
163 List<DpnInterfaces> dpns = elanUtils.getElanDPNByName(elanName);
164 List<IpAddress> dpnsTepIps = getAllTepIpsOfDpns(device, dpns);
165 List<IpAddress> l2GwDevicesTepIps = getAllTepIpsOfL2GwDevices(elanL2gwDevices);
166 preapareRemoteMcastMacEntry(transaction, elanName, device, dpnsTepIps, l2GwDevicesTepIps);
170 * Update mcast macs for this elan.
171 * for all dpns in this elan recompute and update broadcast group
172 * for all l2gw devices in this elan recompute and update remote mcast mac entry
176 * @param elanInstance
180 * @param updateThisDevice
181 * the update this device
182 * @return the listenable future
184 private ListenableFuture<Void> updateMcastMacsForAllElanDevices(String elanName, ElanInstance elanInstance,
185 L2GatewayDevice device, boolean updateThisDevice) {
187 SettableFuture<Void> ft = SettableFuture.create();
190 updateRemoteBroadcastGroupForAllElanDpns(elanInstance);
192 List<DpnInterfaces> dpns = elanUtils.getElanDPNByName(elanName);
194 ConcurrentMap<String, L2GatewayDevice> devices = ElanL2GwCacheUtils
195 .getInvolvedL2GwDevices(elanName);
197 List<IpAddress> dpnsTepIps = getAllTepIpsOfDpns(device, dpns);
198 List<IpAddress> l2GwDevicesTepIps = getAllTepIpsOfL2GwDevices(devices);
199 // if (allTepIps.size() < 2) {
200 // LOG.debug("no other devices are found in the elan {}", elanName);
204 WriteTransaction transaction = broker.newWriteOnlyTransaction();
205 if (updateThisDevice) {
206 preapareRemoteMcastMacEntry(transaction, elanName, device, dpnsTepIps, l2GwDevicesTepIps);
209 // TODO: Need to revisit below logic as logical switches might not be
210 // present to configure RemoteMcastMac entry
211 for (L2GatewayDevice otherDevice : devices.values()) {
212 if (!otherDevice.getDeviceName().equals(device.getDeviceName())) {
213 preapareRemoteMcastMacEntry(transaction, elanName, otherDevice, dpnsTepIps, l2GwDevicesTepIps);
216 return transaction.submit();
220 public void updateRemoteBroadcastGroupForAllElanDpns(ElanInstance elanInfo) {
221 List<DpnInterfaces> dpns = elanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName());
222 for (DpnInterfaces dpn : dpns) {
223 setupElanBroadcastGroups(elanInfo, dpn.getDpId());
227 public void setupElanBroadcastGroups(ElanInstance elanInfo, BigInteger dpnId) {
228 setupElanBroadcastGroups(elanInfo, null, dpnId);
231 public void setupElanBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
232 setupStandardElanBroadcastGroups(elanInfo, dpnInterfaces, dpnId);
233 setupLeavesEtreeBroadcastGroups(elanInfo, dpnInterfaces, dpnId);
236 public void setupStandardElanBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
237 List<Bucket> listBucket = new ArrayList<>();
240 Long elanTag = elanInfo.getElanTag();
241 List<Action> listAction = new ArrayList<>();
242 listAction.add(new ActionGroup(ElanUtils.getElanLocalBCGId(elanTag)).buildAction(++actionKey));
243 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
244 MDSALUtil.WATCH_GROUP));
246 List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId, elanTag);
247 listBucket.addAll(listBucketInfoRemote);
248 long groupId = ElanUtils.getElanRemoteBCGId(elanTag);
249 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
250 MDSALUtil.buildBucketLists(listBucket));
251 LOG.trace("Installing the remote BroadCast Group:{}", group);
252 mdsalManager.syncInstallGroup(dpnId, group);
255 public void setupLeavesEtreeBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
256 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
257 if (etreeInstance != null) {
258 long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue();
259 List<Bucket> listBucket = new ArrayList<>();
262 List<Action> listAction = new ArrayList<>();
263 listAction.add(new ActionGroup(ElanUtils.getEtreeLeafLocalBCGId(etreeLeafTag)).buildAction(++actionKey));
264 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
265 MDSALUtil.WATCH_GROUP));
267 List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId,
269 listBucket.addAll(listBucketInfoRemote);
270 long groupId = ElanUtils.getEtreeLeafRemoteBCGId(etreeLeafTag);
271 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
272 MDSALUtil.buildBucketLists(listBucket));
273 LOG.trace("Installing the remote BroadCast Group:{}", group);
274 mdsalManager.syncInstallGroup(dpnId, group);
278 private DpnInterfaces getDpnInterfaces(ElanDpnInterfacesList elanDpns, BigInteger dpnId) {
279 if (elanDpns != null) {
280 for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) {
281 if (dpnInterface.getDpId().equals(dpnId)) {
289 private List<Bucket> getRemoteBCGroupExternalPortBuckets(ElanDpnInterfacesList elanDpns,
290 DpnInterfaces dpnInterfaces, BigInteger dpnId, int bucketId) {
291 DpnInterfaces currDpnInterfaces = dpnInterfaces != null ? dpnInterfaces : getDpnInterfaces(elanDpns, dpnId);
292 if (currDpnInterfaces == null || !elanUtils.isDpnPresent(currDpnInterfaces.getDpId())
293 || currDpnInterfaces.getInterfaces() == null || currDpnInterfaces.getInterfaces().isEmpty()) {
294 return Collections.emptyList();
296 List<Bucket> listBucketInfo = new ArrayList<>();
297 for (String interfaceName : currDpnInterfaces.getInterfaces()) {
298 if (interfaceManager.isExternalInterface(interfaceName)) {
299 List<Action> listActionInfo = elanItmUtils.getExternalPortItmEgressAction(interfaceName);
300 if (!listActionInfo.isEmpty()) {
301 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
302 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
307 return listBucketInfo;
311 public List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId,
312 int bucketId, long elanTag) {
313 List<Bucket> listBucketInfo = new ArrayList<>();
314 ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
316 if (isVxlan(elanInfo)) {
317 listBucketInfo.addAll(getRemoteBCGroupTunnelBuckets(elanDpns, dpnId, bucketId,
318 elanUtils.isOpenstackVniSemanticsEnforced() ? elanInfo.getSegmentationId() : elanTag));
320 listBucketInfo.addAll(getRemoteBCGroupExternalPortBuckets(elanDpns, dpnInterfaces, dpnId,
321 getNextAvailableBucketId(listBucketInfo.size())));
322 listBucketInfo.addAll(getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId,
323 getNextAvailableBucketId(listBucketInfo.size())));
324 listBucketInfo.addAll(getRemoteBCGroupBucketsOfElanExternalTeps(elanInfo, dpnId,
325 getNextAvailableBucketId(listBucketInfo.size())));
326 return listBucketInfo;
329 public List<Bucket> getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, BigInteger dpnId,
331 List<Bucket> listBucketInfo = new ArrayList<>();
332 ConcurrentMap<String, L2GatewayDevice> map = ElanL2GwCacheUtils
333 .getInvolvedL2GwDevices(elanInfo.getElanInstanceName());
334 for (L2GatewayDevice device : map.values()) {
335 String interfaceName = elanItmUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
336 device.getHwvtepNodeId());
337 if (interfaceName == null) {
340 List<Action> listActionInfo = elanItmUtils.buildTunnelItmEgressActions(interfaceName,
341 ElanUtils.getVxlanSegmentationId(elanInfo));
342 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
343 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
346 return listBucketInfo;
349 public List<Bucket> getRemoteBCGroupBucketsOfElanExternalTeps(ElanInstance elanInfo, BigInteger dpnId,
351 List<Bucket> listBucketInfo = new ArrayList<>();
352 List<ExternalTeps> teps = elanInfo.getExternalTeps();
353 if (teps == null || teps.isEmpty()) {
354 return listBucketInfo;
356 for (ExternalTeps tep : teps) {
357 String interfaceName = elanItmUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
358 tep.getTepIp().toString());
359 if (interfaceName == null) {
360 LOG.error("Could not get interface name to ext tunnel {} {}", dpnId, tep.getTepIp());
363 List<Action> listActionInfo = elanItmUtils.buildTunnelItmEgressActions(interfaceName,
364 elanInfo.getSegmentationId());
365 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
366 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
369 return listBucketInfo;
372 private int getNextAvailableBucketId(int bucketSize) {
373 return bucketSize + 1;
376 @SuppressWarnings("checkstyle:IllegalCatch")
377 private List<Bucket> getRemoteBCGroupTunnelBuckets(ElanDpnInterfacesList elanDpns, BigInteger dpnId, int bucketId,
379 List<Bucket> listBucketInfo = new ArrayList<>();
380 if (elanDpns != null) {
381 for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) {
382 if (elanUtils.isDpnPresent(dpnInterface.getDpId()) && !Objects.equals(dpnInterface.getDpId(), dpnId)
383 && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
385 List<Action> listActionInfo = elanItmUtils.getInternalTunnelItmEgressAction(dpnId,
386 dpnInterface.getDpId(), elanTagOrVni);
387 if (listActionInfo.isEmpty()) {
390 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
391 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
393 } catch (Exception ex) {
394 LOG.error("Logical Group Interface not found between source Dpn - {}, destination Dpn - {} ",
395 dpnId, dpnInterface.getDpId(), ex);
400 return listBucketInfo;
404 * Update remote mcast mac.
414 * @param l2GwDevicesTepIps
415 * the l2 gw devices tep ips
416 * @return the write transaction
418 private void preapareRemoteMcastMacEntry(WriteTransaction transaction, 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(String.valueOf(dhcpDesignatedSwitchTepIp.getValue()));
435 InstanceIdentifier<TerminationPoint> iid =
436 HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, phyLocatorAug);
437 TerminationPoint terminationPoint = new TerminationPointBuilder()
438 .setKey(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 String.valueOf(dhcpDesignatedSwitchTepIp.getValue()), 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 putRemoteMcastMac(transaction, nodeId, logicalSwitchName, remoteTepIps);
455 LOG.info("Adding RemoteMcastMac for node: {} with physical locators: {}", device.getHwvtepNodeId(),
460 * Put remote mcast mac in config DS.
466 * @param logicalSwitchName
467 * the logical switch name
471 private static void putRemoteMcastMac(WriteTransaction transaction, NodeId nodeId, String logicalSwitchName,
472 ArrayList<IpAddress> tepIps) {
473 List<LocatorSet> locators = new ArrayList<>();
474 for (IpAddress tepIp : tepIps) {
475 HwvtepPhysicalLocatorAugmentation phyLocatorAug = HwvtepSouthboundUtils
476 .createHwvtepPhysicalLocatorAugmentation(String.valueOf(tepIp.getValue()));
477 HwvtepPhysicalLocatorRef phyLocRef = new HwvtepPhysicalLocatorRef(
478 HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, phyLocatorAug));
479 locators.add(new LocatorSetBuilder().setLocatorRef(phyLocRef).build());
482 HwvtepLogicalSwitchRef lsRef = new HwvtepLogicalSwitchRef(HwvtepSouthboundUtils
483 .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName)));
484 RemoteMcastMacs remoteMcastMac = new RemoteMcastMacsBuilder()
485 .setMacEntryKey(new MacAddress(ElanConstants.UNKNOWN_DMAC)).setLogicalSwitchRef(lsRef)
486 .setLocatorSet(locators).build();
487 InstanceIdentifier<RemoteMcastMacs> iid = HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId,
488 remoteMcastMac.getKey());
489 ResourceBatchingManager.getInstance().put(ResourceBatchingManager.ShardResource.CONFIG_TOPOLOGY,
490 iid, remoteMcastMac);
495 * Gets all the tep ips of dpns.
501 * @return the all tep ips of dpns and devices
503 private List<IpAddress> getAllTepIpsOfDpns(L2GatewayDevice l2GwDevice, List<DpnInterfaces> dpns) {
504 List<IpAddress> tepIps = new ArrayList<>();
505 for (DpnInterfaces dpn : dpns) {
506 IpAddress internalTunnelIp = elanItmUtils.getSourceDpnTepIp(dpn.getDpId(),
507 new NodeId(l2GwDevice.getHwvtepNodeId()));
508 if (internalTunnelIp != null) {
509 tepIps.add(internalTunnelIp);
516 * Gets the all tep ips of l2 gw devices.
520 * @return the all tep ips of l2 gw devices
522 private static List<IpAddress> getAllTepIpsOfL2GwDevices(ConcurrentMap<String, L2GatewayDevice> devices) {
523 List<IpAddress> tepIps = new ArrayList<>();
524 for (L2GatewayDevice otherDevice : devices.values()) {
525 // There is no need to add the same tep ip to the list.
526 if (!tepIps.contains(otherDevice.getTunnelIp())) {
527 tepIps.add(otherDevice.getTunnelIp());
534 * Handle mcast for elan l2 gw device delete.
537 * the elan instance name
538 * @param elanInstance
540 * @param l2GatewayDevice
541 * the l2 gateway device
542 * @return the listenable future
544 public List<ListenableFuture<Void>> handleMcastForElanL2GwDeviceDelete(String elanName,
545 ElanInstance elanInstance, L2GatewayDevice l2GatewayDevice) {
546 ListenableFuture<Void> updateMcastMacsFuture = updateMcastMacsForAllElanDevices(
547 elanName, elanInstance, l2GatewayDevice, false/* updateThisDevice */);
548 ListenableFuture<Void> deleteRemoteMcastMacFuture = deleteRemoteMcastMac(
549 new NodeId(l2GatewayDevice.getHwvtepNodeId()), elanName);
550 return Arrays.asList(updateMcastMacsFuture, deleteRemoteMcastMacFuture);
554 * Delete remote mcast mac from Hwvtep node.
558 * @param logicalSwitchName
559 * the logical switch name
560 * @return the listenable future
562 private ListenableFuture<Void> deleteRemoteMcastMac(NodeId nodeId, String logicalSwitchName) {
563 InstanceIdentifier<LogicalSwitches> logicalSwitch = HwvtepSouthboundUtils
564 .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName));
565 RemoteMcastMacsKey remoteMcastMacsKey = new RemoteMcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch),
566 new MacAddress(ElanConstants.UNKNOWN_DMAC));
568 LOG.info("Deleting RemoteMcastMacs entry on node: {} for logical switch: {}", nodeId.getValue(),
570 return HwvtepUtils.deleteRemoteMcastMac(broker, nodeId, remoteMcastMacsKey);
574 * Gets the tep ip of designated switch for external tunnel.
578 * @param elanInstanceName
579 * the elan instance name
580 * @return the tep ip of designated switch for external tunnel
582 public IpAddress getTepIpOfDesignatedSwitchForExternalTunnel(L2GatewayDevice l2GwDevice,
583 String elanInstanceName) {
584 IpAddress tepIp = null;
585 if (l2GwDevice.getTunnelIp() == null) {
586 LOG.warn("Tunnel IP not found for {}", l2GwDevice.getDeviceName());
589 DesignatedSwitchForTunnel desgSwitch = getDesignatedSwitchForExternalTunnel(l2GwDevice.getTunnelIp(),
591 if (desgSwitch != null) {
592 tepIp = elanItmUtils.getSourceDpnTepIp(BigInteger.valueOf(desgSwitch.getDpId()),
593 new NodeId(l2GwDevice.getHwvtepNodeId()));
599 * Gets the designated switch for external tunnel.
603 * @param elanInstanceName
604 * the elan instance name
605 * @return the designated switch for external tunnel
607 public DesignatedSwitchForTunnel getDesignatedSwitchForExternalTunnel(IpAddress tunnelIp,
608 String elanInstanceName) {
609 InstanceIdentifier<DesignatedSwitchForTunnel> instanceIdentifier = InstanceIdentifier
610 .builder(DesignatedSwitchesForExternalTunnels.class)
611 .child(DesignatedSwitchForTunnel.class, new DesignatedSwitchForTunnelKey(elanInstanceName, tunnelIp))
613 return MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, instanceIdentifier).orNull();