126004f2e0c818ee6f9d1d4999074c64fa335eba
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / l2gw / listeners / HwvtepRemoteMcastMacListener.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.elan.l2gw.listeners;
9
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import java.util.List;
13 import java.util.concurrent.Callable;
14 import java.util.concurrent.atomic.AtomicBoolean;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.genius.datastoreutils.hwvtep.HwvtepClusteredDataTreeChangeListener;
18 import org.opendaylight.genius.utils.SystemPropertyReader;
19 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
20 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
21 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
22 import org.opendaylight.netvirt.elan.utils.ElanConstants;
23 import org.opendaylight.netvirt.elan.utils.ElanUtils;
24 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
28 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
29 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * The listener class for listening to {@code RemoteMcastMacs}
35  * add/delete/update.
36  *
37  * @see RemoteMcastMacs
38  */
39 public class HwvtepRemoteMcastMacListener
40         extends HwvtepClusteredDataTreeChangeListener<RemoteMcastMacs, HwvtepRemoteMcastMacListener> {
41
42     /** The Constant LOG. */
43     private static final Logger LOG = LoggerFactory.getLogger(HwvtepRemoteMcastMacListener.class);
44
45     /** The node id. */
46     private final NodeId nodeId;
47
48     private final List<IpAddress> expectedPhyLocatorIps;
49
50     private final ElanUtils elanUtils;
51
52     String logicalSwitchName;
53
54     AtomicBoolean executeTask = new AtomicBoolean(true);
55
56     Callable<List<ListenableFuture<Void>>> taskToRun;
57
58     private final JobCoordinator jobCoordinator;
59
60     /**
61      * Instantiates a new remote mcast mac listener.
62      * @param broker DataBroker
63      * @param elanUtils ElanUtils
64      * @param logicalSwitchName LS name of the network
65      * @param l2GatewayDevice L2GatewayDevice
66      * @param expectedPhyLocatorIps List of IP addresses
67      * @param task List of tasks to be executed on callbacks
68      * @param jobCoordinator JobCoordinator
69      * @throws Exception throws Exception
70      */
71     public HwvtepRemoteMcastMacListener(DataBroker broker, ElanUtils elanUtils, String logicalSwitchName,
72                                         L2GatewayDevice l2GatewayDevice,
73                                         List<IpAddress> expectedPhyLocatorIps,
74                                         Callable<List<ListenableFuture<Void>>> task,
75                                         JobCoordinator jobCoordinator) throws Exception {
76         super(RemoteMcastMacs.class, HwvtepRemoteMcastMacListener.class);
77         this.elanUtils = elanUtils;
78         this.nodeId = new NodeId(l2GatewayDevice.getHwvtepNodeId());
79         this.taskToRun = task;
80         this.logicalSwitchName = logicalSwitchName;
81         this.expectedPhyLocatorIps = expectedPhyLocatorIps;
82         this.jobCoordinator = jobCoordinator;
83         LOG.info("registering the listener for mcast mac ");
84         registerListener(LogicalDatastoreType.OPERATIONAL, broker);
85         LOG.info("registered the listener for mcast mac ");
86         if (isDataPresentInOpDs(getWildCardPath())) {
87             LOG.info("mcast mac already present running the task ");
88             if (executeTask.compareAndSet(true, false)) {
89                 runTask();
90             }
91         }
92     }
93
94     private boolean isDataPresentInOpDs(InstanceIdentifier<RemoteMcastMacs> path) throws Exception {
95         Optional<RemoteMcastMacs> mac = elanUtils.read2(LogicalDatastoreType.OPERATIONAL, path);
96         if (!mac.isPresent()) {
97             return false;
98         }
99         if (this.expectedPhyLocatorIps != null && !this.expectedPhyLocatorIps.isEmpty()) {
100             RemoteMcastMacs remoteMcastMac = mac.get();
101             if (remoteMcastMac.getLocatorSet() == null || remoteMcastMac.getLocatorSet().isEmpty()) {
102                 return false;
103             }
104             for (IpAddress ip : this.expectedPhyLocatorIps) {
105                 boolean ipExists = ElanL2GatewayUtils.checkIfPhyLocatorAlreadyExistsInRemoteMcastEntry(this.nodeId,
106                         remoteMcastMac, ip);
107                 if (!ipExists) {
108                     LOG.trace("IP [{}] not found in RemoteMcastMacs for node [{}]", String.valueOf(ip.getValue()),
109                             this.nodeId.getValue());
110                     return false;
111                 }
112             }
113         }
114         return true;
115     }
116
117     @Override
118     public InstanceIdentifier<RemoteMcastMacs> getWildCardPath() {
119         return HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId,
120                 logicalSwitchName, new MacAddress(ElanConstants.UNKNOWN_DMAC));
121     }
122
123     @Override
124     protected HwvtepRemoteMcastMacListener getDataTreeChangeListener() {
125         return this;
126     }
127
128     @Override
129     protected void removed(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs deleted) {
130         LOG.trace("Received Remove DataChange Notification for identifier: {}, RemoteMcastMacs: {}", identifier,
131                 deleted);
132     }
133
134     @Override
135     protected void updated(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs old,
136             RemoteMcastMacs newdata) {
137         LOG.trace("Received Update DataChange Notification for identifier: {}, RemoteMcastMacs old: {}, new: {}."
138                 + "No Action Performed.", identifier, old, newdata);
139     }
140
141     @Override
142     protected void added(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs mcastMac) {
143         LOG.debug("Received Add DataChange Notification for identifier: {}, RemoteMcastMacs: {}", identifier, mcastMac);
144         // No isDataPresentInOpDs check is done as assuming all the expected phy
145         // locator ips will be available during add
146         if (executeTask.compareAndSet(true, false)) {
147             runTask();
148         }
149     }
150
151     @SuppressWarnings("checkstyle:IllegalCatch") // TODO remove when using AutoCloseables
152     void runTask() {
153         try {
154             String jobKey = ElanL2GatewayUtils.getL2GatewayConnectionJobKey(nodeId.getValue(), nodeId.getValue());
155             jobCoordinator.enqueueJob(jobKey, taskToRun,
156                     SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
157         } finally {
158             // TODO https://git.opendaylight.org/gerrit/#/c/44145/
159             // AutoCloseables.closeAndLog(this);
160             try {
161                 close();
162             } catch (Exception e) {
163                 LOG.warn("Failed to close McastMacSwitchListener", e);
164             }
165         }
166     }
167 }