b864f2e2fefbf7313daac1256589141a09a00c67
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / internal / ElanDpnInterfaceClusteredListener.java
1 /*
2  * Copyright (c) 2016, 2017 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.internal;
9
10 import static java.util.Collections.emptyList;
11
12 import java.util.List;
13 import javax.annotation.PreDestroy;
14 import javax.inject.Inject;
15 import javax.inject.Singleton;
16 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
17 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
18 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
19 import org.opendaylight.infrautils.utils.concurrent.Executors;
20 import org.opendaylight.mdsal.binding.api.DataBroker;
21 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
22 import org.opendaylight.netvirt.elan.cache.ElanInstanceCache;
23 import org.opendaylight.netvirt.elan.cache.ElanInstanceDpnsCache;
24 import org.opendaylight.netvirt.elan.l2gw.jobs.BcGroupUpdateJob;
25 import org.opendaylight.netvirt.elan.l2gw.jobs.DpnDmacJob;
26 import org.opendaylight.netvirt.elan.l2gw.jobs.McastUpdateJob;
27 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
28 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
29 import org.opendaylight.netvirt.elan.l2gw.utils.ElanRefUtil;
30 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
31 import org.opendaylight.netvirt.elan.utils.ElanDmacUtils;
32 import org.opendaylight.netvirt.elan.utils.ElanItmUtils;
33 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
34 import org.opendaylight.serviceutils.tools.listener.AbstractClusteredAsyncDataTreeChangeListener;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 @Singleton
44 public class ElanDpnInterfaceClusteredListener
45         extends AbstractClusteredAsyncDataTreeChangeListener<DpnInterfaces> {
46
47     private static final Logger LOG = LoggerFactory.getLogger(ElanDpnInterfaceClusteredListener.class);
48     private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("NetvirtEventLogger");
49
50     private final DataBroker broker;
51     private final EntityOwnershipUtils entityOwnershipUtils;
52     private final ElanL2GatewayUtils elanL2GatewayUtils;
53     private final ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils;
54     private final ElanRefUtil elanRefUtil;
55     private final ElanDmacUtils elanDmacUtils;
56     private final ElanItmUtils elanItmUtils;
57     private final ElanClusterUtils elanClusterUtils;
58     private final JobCoordinator jobCoordinator;
59     private final ElanInstanceCache elanInstanceCache;
60     private final ElanInstanceDpnsCache elanInstanceDpnsCache;
61
62     @Inject
63     public ElanDpnInterfaceClusteredListener(DataBroker broker, EntityOwnershipUtils entityOwnershipUtils,
64                                              ElanL2GatewayUtils elanL2GatewayUtils,
65                                              ElanClusterUtils elanClusterUtils, JobCoordinator jobCoordinator,
66                                              ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils,
67                                              ElanInstanceCache elanInstanceCache,
68                                              ElanInstanceDpnsCache elanInstanceDpnsCache,
69                                              ElanRefUtil elanRefUtil, ElanDmacUtils elanDmacUtils,
70                                              ElanItmUtils elanItmUtils) {
71         super(broker, LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(ElanDpnInterfaces.class)
72                 .child(ElanDpnInterfacesList.class).child(DpnInterfaces.class),
73                 Executors.newListeningSingleThreadExecutor("ElanDpnInterfaceClusteredListener", LOG));
74         this.broker = broker;
75         this.entityOwnershipUtils = entityOwnershipUtils;
76         this.elanL2GatewayUtils = elanL2GatewayUtils;
77         this.elanL2GatewayMulticastUtils = elanL2GatewayMulticastUtils;
78         this.elanRefUtil = elanRefUtil;
79         this.elanDmacUtils = elanDmacUtils;
80         this.elanItmUtils = elanItmUtils;
81         this.elanClusterUtils = elanClusterUtils;
82         this.jobCoordinator = jobCoordinator;
83         this.elanInstanceCache = elanInstanceCache;
84         this.elanInstanceDpnsCache = elanInstanceDpnsCache;
85     }
86
87     public void init() {
88         LOG.info("{} start", getClass().getSimpleName());
89     }
90
91     void handleUpdate(InstanceIdentifier<DpnInterfaces> id, DpnInterfaces dpnInterfaces) {
92         final String elanName = getElanName(id);
93         if (ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName).isEmpty()) {
94             LOG.debug("dpnInterface updation, no external l2 devices to update for elan {} with Dp Id {}", elanName,
95                     dpnInterfaces.getDpId());
96             return;
97         }
98         elanClusterUtils.runOnlyInOwnerNode(elanName, "updating mcast mac upon tunnel event",
99             () -> {
100                 elanL2GatewayMulticastUtils.updateRemoteMcastMacOnElanL2GwDevices(elanName);
101                 return emptyList();
102             });
103     }
104
105     @Override
106     public void remove(InstanceIdentifier<DpnInterfaces> identifier, final DpnInterfaces dpnInterfaces) {
107         // this is the last dpn interface on this elan
108         final String elanName = getElanName(identifier);
109         //Cache need to be updated in all cluster nodes and not only by leader node .
110         //Hence moved out from DJC job
111
112         jobCoordinator.enqueueJob(elanName + ":l2gw", () -> {
113             try {
114                 if (entityOwnershipUtils.isEntityOwner(HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
115                         HwvtepSouthboundConstants.ELAN_ENTITY_NAME)) {
116                     // deleting Elan L2Gw Devices UcastLocalMacs From Dpn
117                     DpnDmacJob.uninstallDmacFromL2gws(elanName, dpnInterfaces, elanL2GatewayUtils, elanRefUtil,
118                             elanDmacUtils);
119
120                     //Removing this dpn from cache to avoid race between this and local ucast mac listener
121                     elanInstanceDpnsCache.remove(getElanName(identifier), dpnInterfaces);
122
123                     // updating remote mcast mac on l2gw devices
124                     McastUpdateJob.updateAllMcastsForDpnDelete(elanName, elanL2GatewayMulticastUtils,
125                             elanClusterUtils, dpnInterfaces.getDpId(), elanItmUtils);
126                     BcGroupUpdateJob.updateAllBcGroups(elanName, elanRefUtil, elanL2GatewayMulticastUtils,
127                             broker, false);
128                 }
129             } finally {
130                 elanInstanceDpnsCache.remove(getElanName(identifier), dpnInterfaces);
131             }
132
133             return null;
134         });
135     }
136
137     @Override
138     public void update(InstanceIdentifier<DpnInterfaces> identifier, DpnInterfaces original,
139                           final DpnInterfaces dpnInterfaces) {
140         List<String> interfaces = dpnInterfaces.getInterfaces();
141         if (interfaces != null && !interfaces.isEmpty()) {
142             LOG.debug("dpninterfaces update fired new size {}", interfaces.size());
143             elanInstanceDpnsCache.remove(getElanName(identifier), original);
144             elanInstanceDpnsCache.add(getElanName(identifier), dpnInterfaces);
145             LOG.debug("dpninterfaces last dpn interface on this elan {} ", dpnInterfaces.key());
146             // this is the last dpn interface on this elan
147             handleUpdate(identifier, dpnInterfaces);
148         }
149     }
150
151     @Override
152     public void add(InstanceIdentifier<DpnInterfaces> identifier, final DpnInterfaces dpnInterfaces) {
153         final String elanName = getElanName(identifier);
154         EVENT_LOGGER.debug("ELAN-DpnInterface, ADD DPN {} Instance {}", dpnInterfaces.getDpId(), elanName);
155         jobCoordinator.enqueueJob(elanName + ":l2gw", () -> {
156             elanInstanceDpnsCache.add(getElanName(identifier), dpnInterfaces);
157             if (entityOwnershipUtils.isEntityOwner(HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
158                     HwvtepSouthboundConstants.ELAN_ENTITY_NAME)) {
159                 ElanInstance elanInstance = elanInstanceCache.get(elanName).orElse(null);
160                 if (elanInstance != null) {
161                     BcGroupUpdateJob.updateAllBcGroups(elanName, elanRefUtil, elanL2GatewayMulticastUtils,
162                             broker, true);
163                     // updating remote mcast mac on l2gw devices
164                     McastUpdateJob.updateAllMcastsForDpnAdd(elanName, elanL2GatewayMulticastUtils,
165                             elanClusterUtils);
166                     DpnDmacJob.installDmacFromL2gws(elanName, dpnInterfaces, elanL2GatewayUtils, elanRefUtil,
167                             elanDmacUtils);
168                 }
169             }
170             return emptyList();
171         });
172     }
173
174     private static String getElanName(InstanceIdentifier<DpnInterfaces> identifier) {
175         return identifier.firstKeyOf(ElanDpnInterfacesList.class).getElanInstanceName();
176     }
177
178     @Override
179     @PreDestroy
180     public void close() {
181         super.close();
182         Executors.shutdownAndAwaitTermination(getExecutorService());
183     }
184 }