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