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.ListenableFuture;
13 import com.google.common.util.concurrent.SettableFuture;
14 import java.math.BigInteger;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.Collections;
18 import java.util.List;
19 import java.util.Objects;
20 import java.util.concurrent.ConcurrentMap;
21 import javax.annotation.Nonnull;
22 import javax.inject.Inject;
23 import javax.inject.Singleton;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
28 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
29 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
30 import org.opendaylight.genius.mdsalutil.MDSALUtil;
31 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
32 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
33 import org.opendaylight.genius.utils.batching.ResourceBatchingManager;
34 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
35 import org.opendaylight.genius.utils.hwvtep.HwvtepUtils;
36 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
37 import org.opendaylight.netvirt.elan.l2gw.jobs.HwvtepDeviceMcastMacUpdateJob;
38 import org.opendaylight.netvirt.elan.utils.ElanConstants;
39 import org.opendaylight.netvirt.elan.utils.ElanItmUtils;
40 import org.opendaylight.netvirt.elan.utils.ElanUtils;
41 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
42 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.DesignatedSwitchesForExternalTunnels;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnel;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnelKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstance;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.elan.instance.ExternalTeps;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSetBuilder;
67 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
68 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
69 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
70 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
71 import org.slf4j.Logger;
72 import org.slf4j.LoggerFactory;
75 * The utility class to handle ELAN L2 Gateway related to multicast.
78 public class ElanL2GatewayMulticastUtils {
80 /** The Constant LOG. */
81 private static final Logger LOG = LoggerFactory.getLogger(ElanL2GatewayMulticastUtils.class);
84 private final DataBroker broker;
85 private final ManagedNewTransactionRunner txRunner;
87 private final ElanItmUtils elanItmUtils;
88 private final JobCoordinator jobCoordinator;
89 private final ElanUtils elanUtils;
90 private final IMdsalApiManager mdsalManager;
91 private final IInterfaceManager interfaceManager;
94 public ElanL2GatewayMulticastUtils(DataBroker broker, ElanItmUtils elanItmUtils, JobCoordinator jobCoordinator,
95 ElanUtils elanUtils, IMdsalApiManager mdsalManager, IInterfaceManager interfaceManager) {
97 this.txRunner = new ManagedNewTransactionRunnerImpl(broker);
98 this.elanItmUtils = elanItmUtils;
99 this.jobCoordinator = jobCoordinator;
100 this.elanUtils = elanUtils;
101 this.mdsalManager = mdsalManager;
102 this.interfaceManager = interfaceManager;
106 * Handle mcast for elan l2 gw device add.
107 * @param elanName the elan name
108 * @param elanInstance elanInstace
109 * @param device the device
110 * @return the listenable future
112 public ListenableFuture<Void> handleMcastForElanL2GwDeviceAdd(String elanName, ElanInstance elanInstance,
113 L2GatewayDevice device) {
114 return updateMcastMacsForAllElanDevices(elanName, elanInstance, device, true/* updateThisDevice */);
118 * Updates the remote mcast mac table for all the devices in this elan
119 * includes all the dpn tep ips and other devices tep ips in broadcast
123 * the elan to be updated
124 * @return the listenable future
126 @SuppressWarnings("checkstyle:IllegalCatch")
127 public ListenableFuture<Void> updateRemoteMcastMacOnElanL2GwDevices(String elanName) {
128 return txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
129 for (L2GatewayDevice device : ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName).values()) {
130 prepareRemoteMcastMacUpdateOnDevice(tx, elanName, device);
135 public void scheduleMcastMacUpdateJob(String elanName, L2GatewayDevice device) {
136 HwvtepDeviceMcastMacUpdateJob job = new HwvtepDeviceMcastMacUpdateJob(this, elanName,device);
137 jobCoordinator.enqueueJob(job.getJobKey(), job);
141 * Update remote mcast mac on elan l2 gw device.
147 * @return the listenable future
149 public ListenableFuture<Void> updateRemoteMcastMacOnElanL2GwDevice(String elanName, L2GatewayDevice device) {
150 return txRunner.callWithNewWriteOnlyTransactionAndSubmit(
151 tx -> prepareRemoteMcastMacUpdateOnDevice(tx, elanName, device));
154 public void prepareRemoteMcastMacUpdateOnDevice(WriteTransaction transaction,String elanName,
155 L2GatewayDevice device) {
156 ConcurrentMap<String, L2GatewayDevice> elanL2gwDevices = ElanL2GwCacheUtils
157 .getInvolvedL2GwDevices(elanName);
158 List<DpnInterfaces> dpns = elanUtils.getElanDPNByName(elanName);
159 List<IpAddress> dpnsTepIps = getAllTepIpsOfDpns(device, dpns);
160 List<IpAddress> l2GwDevicesTepIps = getAllTepIpsOfL2GwDevices(elanL2gwDevices);
161 preapareRemoteMcastMacEntry(transaction, elanName, device, dpnsTepIps, l2GwDevicesTepIps);
165 * Update mcast macs for this elan.
166 * for all dpns in this elan recompute and update broadcast group
167 * for all l2gw devices in this elan recompute and update remote mcast mac entry
171 * @param elanInstance
175 * @param updateThisDevice
176 * the update this device
177 * @return the listenable future
179 private ListenableFuture<Void> updateMcastMacsForAllElanDevices(String elanName, ElanInstance elanInstance,
180 L2GatewayDevice device, boolean updateThisDevice) {
182 SettableFuture<Void> ft = SettableFuture.create();
185 updateRemoteBroadcastGroupForAllElanDpns(elanInstance);
187 List<DpnInterfaces> dpns = elanUtils.getElanDPNByName(elanName);
189 ConcurrentMap<String, L2GatewayDevice> devices = ElanL2GwCacheUtils
190 .getInvolvedL2GwDevices(elanName);
192 List<IpAddress> dpnsTepIps = getAllTepIpsOfDpns(device, dpns);
193 List<IpAddress> l2GwDevicesTepIps = getAllTepIpsOfL2GwDevices(devices);
194 // if (allTepIps.size() < 2) {
195 // LOG.debug("no other devices are found in the elan {}", elanName);
199 return txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
200 if (updateThisDevice) {
201 preapareRemoteMcastMacEntry(tx, elanName, device, dpnsTepIps, l2GwDevicesTepIps);
204 // TODO: Need to revisit below logic as logical switches might not be
205 // present to configure RemoteMcastMac entry
206 for (L2GatewayDevice otherDevice : devices.values()) {
207 if (!otherDevice.getDeviceName().equals(device.getDeviceName())) {
208 preapareRemoteMcastMacEntry(tx, elanName, otherDevice, dpnsTepIps, l2GwDevicesTepIps);
215 public void updateRemoteBroadcastGroupForAllElanDpns(ElanInstance elanInfo) {
216 List<DpnInterfaces> dpns = elanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName());
217 for (DpnInterfaces dpn : dpns) {
218 setupElanBroadcastGroups(elanInfo, dpn.getDpId());
222 public void setupElanBroadcastGroups(ElanInstance elanInfo, BigInteger dpnId) {
223 setupElanBroadcastGroups(elanInfo, null, dpnId);
226 public void setupElanBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
227 setupStandardElanBroadcastGroups(elanInfo, dpnInterfaces, dpnId);
228 setupLeavesEtreeBroadcastGroups(elanInfo, dpnInterfaces, dpnId);
231 public void setupStandardElanBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
232 List<Bucket> listBucket = new ArrayList<>();
235 Long elanTag = elanInfo.getElanTag();
236 List<Action> listAction = new ArrayList<>();
237 listAction.add(new ActionGroup(ElanUtils.getElanLocalBCGId(elanTag)).buildAction(++actionKey));
238 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
239 MDSALUtil.WATCH_GROUP));
241 List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId, elanTag);
242 listBucket.addAll(listBucketInfoRemote);
243 long groupId = ElanUtils.getElanRemoteBCGId(elanTag);
244 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
245 MDSALUtil.buildBucketLists(listBucket));
246 LOG.trace("Installing the remote BroadCast Group:{}", group);
247 mdsalManager.syncInstallGroup(dpnId, group);
250 public void setupLeavesEtreeBroadcastGroups(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId) {
251 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
252 if (etreeInstance != null) {
253 long etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue();
254 List<Bucket> listBucket = new ArrayList<>();
257 List<Action> listAction = new ArrayList<>();
258 listAction.add(new ActionGroup(ElanUtils.getEtreeLeafLocalBCGId(etreeLeafTag)).buildAction(++actionKey));
259 listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
260 MDSALUtil.WATCH_GROUP));
262 List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId,
264 listBucket.addAll(listBucketInfoRemote);
265 long groupId = ElanUtils.getEtreeLeafRemoteBCGId(etreeLeafTag);
266 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
267 MDSALUtil.buildBucketLists(listBucket));
268 LOG.trace("Installing the remote BroadCast Group:{}", group);
269 mdsalManager.syncInstallGroup(dpnId, group);
273 private DpnInterfaces getDpnInterfaces(ElanDpnInterfacesList elanDpns, BigInteger dpnId) {
274 if (elanDpns != null) {
275 for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) {
276 if (dpnInterface.getDpId().equals(dpnId)) {
284 private List<Bucket> getRemoteBCGroupExternalPortBuckets(ElanDpnInterfacesList elanDpns,
285 DpnInterfaces dpnInterfaces, BigInteger dpnId, int bucketId) {
286 DpnInterfaces currDpnInterfaces = dpnInterfaces != null ? dpnInterfaces : getDpnInterfaces(elanDpns, dpnId);
287 if (currDpnInterfaces == null || !elanUtils.isDpnPresent(currDpnInterfaces.getDpId())
288 || currDpnInterfaces.getInterfaces() == null || currDpnInterfaces.getInterfaces().isEmpty()) {
289 return Collections.emptyList();
291 List<Bucket> listBucketInfo = new ArrayList<>();
292 for (String interfaceName : currDpnInterfaces.getInterfaces()) {
293 if (interfaceManager.isExternalInterface(interfaceName)) {
294 List<Action> listActionInfo = elanItmUtils.getExternalPortItmEgressAction(interfaceName);
295 if (!listActionInfo.isEmpty()) {
296 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
297 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
302 return listBucketInfo;
306 public List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo, DpnInterfaces dpnInterfaces, BigInteger dpnId,
307 int bucketId, long elanTag) {
308 List<Bucket> listBucketInfo = new ArrayList<>();
309 ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
311 if (isVxlan(elanInfo)) {
312 listBucketInfo.addAll(getRemoteBCGroupTunnelBuckets(elanDpns, dpnId, bucketId,
313 elanUtils.isOpenstackVniSemanticsEnforced() ? elanInfo.getSegmentationId() : elanTag));
315 listBucketInfo.addAll(getRemoteBCGroupExternalPortBuckets(elanDpns, dpnInterfaces, dpnId,
316 getNextAvailableBucketId(listBucketInfo.size())));
317 listBucketInfo.addAll(getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId,
318 getNextAvailableBucketId(listBucketInfo.size())));
319 listBucketInfo.addAll(getRemoteBCGroupBucketsOfElanExternalTeps(elanInfo, dpnId,
320 getNextAvailableBucketId(listBucketInfo.size())));
321 return listBucketInfo;
324 public List<Bucket> getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, BigInteger dpnId,
326 List<Bucket> listBucketInfo = new ArrayList<>();
327 ConcurrentMap<String, L2GatewayDevice> map = ElanL2GwCacheUtils
328 .getInvolvedL2GwDevices(elanInfo.getElanInstanceName());
329 for (L2GatewayDevice device : map.values()) {
330 String interfaceName = elanItmUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
331 device.getHwvtepNodeId());
332 if (interfaceName == null) {
335 List<Action> listActionInfo = elanItmUtils.buildTunnelItmEgressActions(interfaceName,
336 ElanUtils.getVxlanSegmentationId(elanInfo));
337 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
338 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
341 return listBucketInfo;
344 public List<Bucket> getRemoteBCGroupBucketsOfElanExternalTeps(ElanInstance elanInfo, BigInteger dpnId,
346 List<Bucket> listBucketInfo = new ArrayList<>();
347 List<ExternalTeps> teps = elanInfo.getExternalTeps();
348 if (teps == null || teps.isEmpty()) {
349 return listBucketInfo;
351 for (ExternalTeps tep : teps) {
352 String interfaceName = elanItmUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
353 tep.getTepIp().toString());
354 if (interfaceName == null) {
355 LOG.error("Could not get interface name to ext tunnel {} {}", dpnId, tep.getTepIp());
358 List<Action> listActionInfo = elanItmUtils.buildTunnelItmEgressActions(interfaceName,
359 elanInfo.getSegmentationId());
360 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
361 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
364 return listBucketInfo;
367 private int getNextAvailableBucketId(int bucketSize) {
368 return bucketSize + 1;
371 @SuppressWarnings("checkstyle:IllegalCatch")
372 private List<Bucket> getRemoteBCGroupTunnelBuckets(ElanDpnInterfacesList elanDpns, BigInteger dpnId, int bucketId,
374 List<Bucket> listBucketInfo = new ArrayList<>();
375 if (elanDpns != null) {
376 for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) {
377 if (elanUtils.isDpnPresent(dpnInterface.getDpId()) && !Objects.equals(dpnInterface.getDpId(), dpnId)
378 && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
380 List<Action> listActionInfo = elanItmUtils.getInternalTunnelItmEgressAction(dpnId,
381 dpnInterface.getDpId(), elanTagOrVni);
382 if (listActionInfo.isEmpty()) {
385 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
386 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
388 } catch (Exception ex) {
389 LOG.error("Logical Group Interface not found between source Dpn - {}, destination Dpn - {} ",
390 dpnId, dpnInterface.getDpId(), ex);
395 return listBucketInfo;
399 * Update remote mcast mac.
409 * @param l2GwDevicesTepIps
410 * the l2 gw devices tep ips
411 * @return the write transaction
413 private void preapareRemoteMcastMacEntry(WriteTransaction transaction, String elanName,
414 L2GatewayDevice device, List<IpAddress> dpnsTepIps,
415 List<IpAddress> l2GwDevicesTepIps) {
416 NodeId nodeId = new NodeId(device.getHwvtepNodeId());
418 ArrayList<IpAddress> remoteTepIps = new ArrayList<>(l2GwDevicesTepIps);
419 remoteTepIps.remove(device.getTunnelIp());
420 remoteTepIps.addAll(dpnsTepIps);
421 IpAddress dhcpDesignatedSwitchTepIp = getTepIpOfDesignatedSwitchForExternalTunnel(device, elanName);
422 if (dpnsTepIps.isEmpty()) {
423 // If no dpns in elan, configure dhcp designated switch Tep Ip as a
424 // physical locator in l2 gw device
425 if (dhcpDesignatedSwitchTepIp != null) {
426 remoteTepIps.add(dhcpDesignatedSwitchTepIp);
428 HwvtepPhysicalLocatorAugmentation phyLocatorAug = HwvtepSouthboundUtils
429 .createHwvtepPhysicalLocatorAugmentation(String.valueOf(dhcpDesignatedSwitchTepIp.getValue()));
430 InstanceIdentifier<TerminationPoint> iid =
431 HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, phyLocatorAug);
432 TerminationPoint terminationPoint = new TerminationPointBuilder()
433 .setKey(HwvtepSouthboundUtils.getTerminationPointKey(phyLocatorAug))
434 .addAugmentation(HwvtepPhysicalLocatorAugmentation.class, phyLocatorAug).build();
435 ResourceBatchingManager.getInstance().put(ResourceBatchingManager.ShardResource.CONFIG_TOPOLOGY,
436 iid, terminationPoint);
437 LOG.info("Adding PhysicalLocator for node: {} with Dhcp designated switch Tep Ip {} "
438 + "as physical locator, elan {}", device.getHwvtepNodeId(),
439 String.valueOf(dhcpDesignatedSwitchTepIp.getValue()), elanName);
441 LOG.warn("Dhcp designated switch Tep Ip not found for l2 gw node {} and elan {}",
442 device.getHwvtepNodeId(), elanName);
445 if (dhcpDesignatedSwitchTepIp != null && !remoteTepIps.contains(dhcpDesignatedSwitchTepIp)) {
446 remoteTepIps.add(dhcpDesignatedSwitchTepIp);
448 String logicalSwitchName = ElanL2GatewayUtils.getLogicalSwitchFromElan(elanName);
449 putRemoteMcastMac(transaction, nodeId, logicalSwitchName, remoteTepIps);
450 LOG.info("Adding RemoteMcastMac for node: {} with physical locators: {}", device.getHwvtepNodeId(),
455 * Put remote mcast mac in config DS.
461 * @param logicalSwitchName
462 * the logical switch name
466 private static void putRemoteMcastMac(WriteTransaction transaction, NodeId nodeId, String logicalSwitchName,
467 ArrayList<IpAddress> tepIps) {
468 List<LocatorSet> locators = new ArrayList<>();
469 for (IpAddress tepIp : tepIps) {
470 HwvtepPhysicalLocatorAugmentation phyLocatorAug = HwvtepSouthboundUtils
471 .createHwvtepPhysicalLocatorAugmentation(String.valueOf(tepIp.getValue()));
472 HwvtepPhysicalLocatorRef phyLocRef = new HwvtepPhysicalLocatorRef(
473 HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, phyLocatorAug));
474 locators.add(new LocatorSetBuilder().setLocatorRef(phyLocRef).build());
477 HwvtepLogicalSwitchRef lsRef = new HwvtepLogicalSwitchRef(HwvtepSouthboundUtils
478 .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName)));
479 RemoteMcastMacs remoteMcastMac = new RemoteMcastMacsBuilder()
480 .setMacEntryKey(new MacAddress(ElanConstants.UNKNOWN_DMAC)).setLogicalSwitchRef(lsRef)
481 .setLocatorSet(locators).build();
482 InstanceIdentifier<RemoteMcastMacs> iid = HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId,
483 remoteMcastMac.getKey());
484 ResourceBatchingManager.getInstance().put(ResourceBatchingManager.ShardResource.CONFIG_TOPOLOGY,
485 iid, remoteMcastMac);
490 * Gets all the tep ips of dpns.
496 * @return the all tep ips of dpns and devices
498 private List<IpAddress> getAllTepIpsOfDpns(L2GatewayDevice l2GwDevice, List<DpnInterfaces> dpns) {
499 List<IpAddress> tepIps = new ArrayList<>();
500 for (DpnInterfaces dpn : dpns) {
501 IpAddress internalTunnelIp = elanItmUtils.getSourceDpnTepIp(dpn.getDpId(),
502 new NodeId(l2GwDevice.getHwvtepNodeId()));
503 if (internalTunnelIp != null) {
504 tepIps.add(internalTunnelIp);
511 * Gets the all tep ips of l2 gw devices.
515 * @return the all tep ips of l2 gw devices
517 private static List<IpAddress> getAllTepIpsOfL2GwDevices(ConcurrentMap<String, L2GatewayDevice> devices) {
518 List<IpAddress> tepIps = new ArrayList<>();
519 for (L2GatewayDevice otherDevice : devices.values()) {
520 // There is no need to add the same tep ip to the list.
521 if (!tepIps.contains(otherDevice.getTunnelIp())) {
522 tepIps.add(otherDevice.getTunnelIp());
529 * Handle mcast for elan l2 gw device delete.
532 * the elan instance name
533 * @param elanInstance
535 * @param l2GatewayDevice
536 * the l2 gateway device
537 * @return the listenable future
539 public List<ListenableFuture<Void>> handleMcastForElanL2GwDeviceDelete(String elanName,
540 ElanInstance elanInstance, L2GatewayDevice l2GatewayDevice) {
541 ListenableFuture<Void> updateMcastMacsFuture = updateMcastMacsForAllElanDevices(
542 elanName, elanInstance, l2GatewayDevice, false/* updateThisDevice */);
543 ListenableFuture<Void> deleteRemoteMcastMacFuture = deleteRemoteMcastMac(
544 new NodeId(l2GatewayDevice.getHwvtepNodeId()), elanName);
545 return Arrays.asList(updateMcastMacsFuture, deleteRemoteMcastMacFuture);
549 * Delete remote mcast mac from Hwvtep node.
553 * @param logicalSwitchName
554 * the logical switch name
555 * @return the listenable future
557 private ListenableFuture<Void> deleteRemoteMcastMac(NodeId nodeId, String logicalSwitchName) {
558 InstanceIdentifier<LogicalSwitches> logicalSwitch = HwvtepSouthboundUtils
559 .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName));
560 RemoteMcastMacsKey remoteMcastMacsKey = new RemoteMcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch),
561 new MacAddress(ElanConstants.UNKNOWN_DMAC));
563 LOG.info("Deleting RemoteMcastMacs entry on node: {} for logical switch: {}", nodeId.getValue(),
565 return HwvtepUtils.deleteRemoteMcastMac(broker, nodeId, remoteMcastMacsKey);
569 * Gets the tep ip of designated switch for external tunnel.
573 * @param elanInstanceName
574 * the elan instance name
575 * @return the tep ip of designated switch for external tunnel
577 public IpAddress getTepIpOfDesignatedSwitchForExternalTunnel(L2GatewayDevice l2GwDevice,
578 String elanInstanceName) {
579 IpAddress tepIp = null;
580 if (l2GwDevice.getTunnelIp() == null) {
581 LOG.warn("Tunnel IP not found for {}", l2GwDevice.getDeviceName());
584 DesignatedSwitchForTunnel desgSwitch = getDesignatedSwitchForExternalTunnel(l2GwDevice.getTunnelIp(),
586 if (desgSwitch != null) {
587 tepIp = elanItmUtils.getSourceDpnTepIp(BigInteger.valueOf(desgSwitch.getDpId()),
588 new NodeId(l2GwDevice.getHwvtepNodeId()));
594 * Gets the designated switch for external tunnel.
598 * @param elanInstanceName
599 * the elan instance name
600 * @return the designated switch for external tunnel
602 public DesignatedSwitchForTunnel getDesignatedSwitchForExternalTunnel(IpAddress tunnelIp,
603 String elanInstanceName) {
604 InstanceIdentifier<DesignatedSwitchForTunnel> instanceIdentifier = InstanceIdentifier
605 .builder(DesignatedSwitchesForExternalTunnels.class)
606 .child(DesignatedSwitchForTunnel.class, new DesignatedSwitchForTunnelKey(elanInstanceName, tunnelIp))
608 return MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, instanceIdentifier).orNull();