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