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.vpnservice.elan.l2gw.listeners;
10 import java.util.ArrayList;
11 import java.util.List;
12 import java.util.concurrent.Callable;
13 import java.util.concurrent.atomic.AtomicBoolean;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
17 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase;
20 import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
21 import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayUtils;
22 import org.opendaylight.vpnservice.elan.utils.ElanConstants;
23 import org.opendaylight.vpnservice.elan.utils.ElanUtils;
24 import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
25 import org.opendaylight.vpnservice.utils.SystemPropertyReader;
26 import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundUtils;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
35 import org.opendaylight.yangtools.yang.binding.DataObject;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
40 import com.google.common.base.Optional;
41 import com.google.common.util.concurrent.ListenableFuture;
44 * The listener class for listening to {@code RemoteMcastMacs}
47 * @see RemoteMcastMacs
49 public class HwvtepRemoteMcastMacListener
50 extends AsyncDataChangeListenerBase<RemoteMcastMacs, HwvtepRemoteMcastMacListener> {
52 /** The Constant LOG. */
53 private static final Logger LOG = LoggerFactory.getLogger(HwvtepRemoteMcastMacListener.class);
56 private NodeId nodeId;
58 private List<IpAddress> expectedPhyLocatorIps;
62 String logicalSwitchName;
64 AtomicBoolean executeTask = new AtomicBoolean(true);
66 Callable<List<ListenableFuture<Void>>> taskToRun;
68 static DataStoreJobCoordinator dataStoreJobCoordinator;
70 public static void setDataStoreJobCoordinator(DataStoreJobCoordinator ds) {
71 dataStoreJobCoordinator = ds;
75 * Instantiates a new remote mcast mac listener.
78 * the mdsal databroker reference
79 * @param logicalSwitchName
80 * the logical switch name
81 * @param l2GatewayDevice
82 * the l2 gateway device
83 * @param expectedPhyLocatorIps
84 * the expected phy locator ips
86 * the task to be run upon data presence
90 public HwvtepRemoteMcastMacListener(DataBroker broker, String logicalSwitchName, L2GatewayDevice l2GatewayDevice,
91 List<IpAddress> expectedPhyLocatorIps, Callable<List<ListenableFuture<Void>>> task) throws Exception {
92 super(RemoteMcastMacs.class, HwvtepRemoteMcastMacListener.class);
93 this.nodeId = new NodeId(l2GatewayDevice.getHwvtepNodeId());
95 this.taskToRun = task;
96 this.logicalSwitchName = logicalSwitchName;
97 this.expectedPhyLocatorIps = expectedPhyLocatorIps;
98 LOG.info("registering the listener for mcast mac ");
99 registerListener(LogicalDatastoreType.OPERATIONAL, broker);
100 LOG.info("registered the listener for mcast mac ");
101 if (isDataPresentInOpDs(getWildCardPath())) {
102 LOG.info("mcast mac already present running the task ");
103 if (executeTask.compareAndSet(true, false)) {
109 private boolean isDataPresentInOpDs(InstanceIdentifier<RemoteMcastMacs> path) throws Exception {
110 Optional<RemoteMcastMacs> mac = null;
112 mac = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, path);
113 } catch (Throwable e) {
115 if (mac == null || !mac.isPresent()) {
118 if (this.expectedPhyLocatorIps != null && !this.expectedPhyLocatorIps.isEmpty()) {
119 RemoteMcastMacs remoteMcastMac = mac.get();
120 if (remoteMcastMac.getLocatorSet() == null || remoteMcastMac.getLocatorSet().isEmpty()) {
123 for (IpAddress ip : this.expectedPhyLocatorIps) {
124 boolean ipExists = ElanL2GatewayUtils.checkIfPhyLocatorAlreadyExistsInRemoteMcastEntry(this.nodeId,
127 LOG.trace("IP [{}] not found in RemoteMcastMacs for node [{}]", String.valueOf(ip.getValue()),
128 this.nodeId.getValue());
140 * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
144 public InstanceIdentifier<RemoteMcastMacs> getWildCardPath() {
145 return HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId,
146 logicalSwitchName, new MacAddress(ElanConstants.UNKNOWN_DMAC));
153 * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
154 * getDataChangeListener()
157 protected DataChangeListener getDataChangeListener() {
158 return HwvtepRemoteMcastMacListener.this;
165 * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
166 * getDataChangeScope()
169 protected AsyncDataBroker.DataChangeScope getDataChangeScope() {
170 return AsyncDataBroker.DataChangeScope.BASE;
177 * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
178 * remove(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
179 * org.opendaylight.yangtools.yang.binding.DataObject)
182 protected void remove(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs deleted) {
183 LOG.trace("Received Remove DataChange Notification for identifier: {}, RemoteMcastMacs: {}", identifier,
191 * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
192 * update(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
193 * org.opendaylight.yangtools.yang.binding.DataObject,
194 * org.opendaylight.yangtools.yang.binding.DataObject)
197 protected void update(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs old,
198 RemoteMcastMacs newdata) {
199 LOG.trace("Received Update DataChange Notification for identifier: {}, RemoteMcastMacs old: {}, new: {}."
200 + "No Action Performed.", identifier, old, newdata);
207 * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
208 * add(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
209 * org.opendaylight.yangtools.yang.binding.DataObject)
212 protected void add(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs mcastMac) {
213 LOG.debug("Received Add DataChange Notification for identifier: {}, RemoteMcastMacs: {}", identifier, mcastMac);
214 // No isDataPresentInOpDs check is done as assuming all the expected phy
215 // locator ips will be available during add
216 if (executeTask.compareAndSet(true, false)) {
224 String jobKey = ElanL2GatewayUtils.getL2GatewayConnectionJobKey(nodeId.getValue(), nodeId.getValue());
225 dataStoreJobCoordinator.enqueueJob(jobKey, taskToRun, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
226 } catch (Exception e) {
227 LOG.error("Failed to handle remote mcast mac - add: {}", e);
231 } catch (Exception e) {
232 LOG.warn("Failed to close McastMacSwitchListener: {}", e);