1de43567ca2a7398e027b564009a803446bfb1dd
[netvirt.git] / vpnservice / elanmanager / elanmanager-impl / src / main / java / org / opendaylight / netvirt / elan / internal / ElanServiceProvider.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
9 package org.opendaylight.netvirt.elan.internal;
10
11 import com.google.common.base.Optional;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.Collections;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.concurrent.Future;
20 import java.util.function.BiFunction;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
23 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
26 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
27 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
28 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
29 import org.opendaylight.genius.interfacemanager.exceptions.InterfaceAlreadyExistsException;
30 import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
31 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
32 import org.opendaylight.genius.itm.api.IITMProvider;
33 import org.opendaylight.genius.mdsalutil.MDSALUtil;
34 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
35 import org.opendaylight.netvirt.elan.l2gw.internal.ElanL2GatewayProvider;
36 import org.opendaylight.netvirt.elan.statisitcs.ElanStatisticsImpl;
37 import org.opendaylight.netvirt.elan.statusanddiag.ElanStatusMonitor;
38 import org.opendaylight.netvirt.elan.utils.CacheElanInstanceListener;
39 import org.opendaylight.netvirt.elan.utils.CacheElanInterfaceListener;
40 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
41 import org.opendaylight.netvirt.elan.utils.ElanConstants;
42 import org.opendaylight.netvirt.elan.utils.ElanForwardingEntriesHandler;
43 import org.opendaylight.netvirt.elan.utils.ElanUtils;
44 import org.opendaylight.netvirt.elanmanager.api.IElanService;
45 import org.opendaylight.netvirt.elanmanager.exceptions.MacNotFoundException;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstance;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstanceBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface.EtreeInterfaceType;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterfaceBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.Elan;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.statistics.rev150824.ElanStatisticsService;
73 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
75 import org.opendaylight.yangtools.yang.common.RpcResult;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
78
79 public class ElanServiceProvider implements BindingAwareProvider, IElanService, AutoCloseable {
80
81     private IdManagerService idManager;
82     private IMdsalApiManager mdsalManager;
83     private IInterfaceManager interfaceManager;
84     private OdlInterfaceRpcService interfaceManagerRpcService;
85     private ElanInstanceManager elanInstanceManager;
86     private ElanForwardingEntriesHandler elanForwardingEntriesHandler;
87     private ElanBridgeManager bridgeMgr;
88
89     public IdManagerService getIdManager() {
90         return idManager;
91     }
92
93     public ElanForwardingEntriesHandler getElanForwardingEntriesHandler() {
94         return elanForwardingEntriesHandler;
95     }
96
97     public ElanPacketInHandler getElanPacketInHandler() {
98         return elanPacketInHandler;
99     }
100
101     public ElanSmacFlowEventListener getElanSmacFlowEventListener() {
102         return elanSmacFlowEventListener;
103     }
104
105     public ElanInterfaceStateChangeListener getElanInterfaceStateChangeListener() {
106         return elanInterfaceStateChangeListener;
107     }
108
109     public ElanInterfaceStateClusteredListener getInfStateChangeClusteredListener() {
110         return infStateChangeClusteredListener;
111     }
112
113     public ElanDpnInterfaceClusteredListener getElanDpnInterfaceClusteredListener() {
114         return elanDpnInterfaceClusteredListener;
115     }
116
117     public ElanNodeListener getElanNodeListener() {
118         return elanNodeListener;
119     }
120
121     public NotificationService getNotificationService() {
122         return notificationService;
123     }
124
125     public RpcProviderRegistry getRpcProviderRegistry() {
126         return rpcProviderRegistry;
127     }
128
129     public ElanL2GatewayProvider getElanL2GatewayProvider() {
130         return elanL2GatewayProvider;
131     }
132
133     public static ElanStatusMonitor getElanstatusmonitor() {
134         return elanStatusMonitor;
135     }
136
137     public ElanItmEventListener getElanItmEventListener() {
138         return elanItmEventListener;
139     }
140
141     public static Logger getLogger() {
142         return logger;
143     }
144
145     private ElanInterfaceManager elanInterfaceManager;
146     private ElanPacketInHandler elanPacketInHandler;
147     private ElanSmacFlowEventListener elanSmacFlowEventListener;
148     private ElanInterfaceStateChangeListener elanInterfaceStateChangeListener;
149     private ElanInterfaceStateClusteredListener infStateChangeClusteredListener;
150     private ElanDpnInterfaceClusteredListener elanDpnInterfaceClusteredListener;
151     private ElanNodeListener elanNodeListener;
152     private NotificationService notificationService;
153     private RpcProviderRegistry rpcProviderRegistry;
154     private IITMProvider itmManager;
155     private ItmRpcService itmRpcService;
156     private DataBroker broker;
157     private ElanL2GatewayProvider elanL2GatewayProvider;
158     private ElanStatisticsService interfaceStatsService;
159     private EntityOwnershipService entityOwnershipService;
160     private CacheElanInstanceListener cacheElanInstanceListener;
161     private CacheElanInterfaceListener cacheElanInterfaceListener;
162     private static final ElanStatusMonitor elanStatusMonitor = ElanStatusMonitor.getInstance();
163     static DataStoreJobCoordinator dataStoreJobCoordinator;
164     private ElanOvsdbNodeListener elanOvsdbNodeListener;
165
166     private boolean generateIntBridgeMac = true;
167
168     public static void setDataStoreJobCoordinator(DataStoreJobCoordinator ds) {
169         dataStoreJobCoordinator = ds;
170     }
171
172     public void setBroker(DataBroker broker) {
173         this.broker = broker;
174     }
175
176     public static DataStoreJobCoordinator getDataStoreJobCoordinator() {
177         if (dataStoreJobCoordinator == null) {
178             dataStoreJobCoordinator = DataStoreJobCoordinator.getInstance();
179         }
180         return dataStoreJobCoordinator;
181     }
182
183     public ElanServiceProvider(RpcProviderRegistry rpcRegistry) {
184         rpcProviderRegistry = rpcRegistry;
185         elanStatusMonitor.registerMbean();
186     }
187
188     // private ElanInterfaceStateChangeListener elanInterfaceEventListener;
189     private ElanItmEventListener elanItmEventListener;
190
191     private static final Logger logger = LoggerFactory.getLogger(ElanServiceProvider.class);
192
193     @Override
194     public void onSessionInitiated(ProviderContext session) {
195         elanStatusMonitor.reportStatus("STARTING");
196         try {
197             createIdPool();
198             getDataStoreJobCoordinator();
199             broker = session.getSALService(DataBroker.class);
200
201             bridgeMgr = new ElanBridgeManager(broker);
202             elanOvsdbNodeListener = new ElanOvsdbNodeListener(broker, generateIntBridgeMac, bridgeMgr, this);
203             ElanUtils.setElanServiceProvider(this);
204             elanForwardingEntriesHandler = ElanForwardingEntriesHandler.getElanForwardingEntriesHandler(this);
205             elanInterfaceManager = ElanInterfaceManager.getElanInterfaceManager(this);
206             elanInstanceManager = ElanInstanceManager.getElanInstanceManager(this);
207             elanNodeListener = ElanNodeListener.getElanNodeListener(this);
208             elanPacketInHandler = ElanPacketInHandler.getElanPacketInHandler(this);
209             elanSmacFlowEventListener = ElanSmacFlowEventListener.getElanSmacFlowEventListener(this);
210             // Initialize statistics rpc provider for elan
211             interfaceStatsService = ElanStatisticsImpl.getElanStatisticsService(this);
212             rpcProviderRegistry.addRpcImplementation(ElanStatisticsService.class, interfaceStatsService);
213             elanInterfaceStateChangeListener = ElanInterfaceStateChangeListener
214                     .getElanInterfaceStateChangeListener(this);
215             infStateChangeClusteredListener = ElanInterfaceStateClusteredListener
216                     .getElanInterfaceStateClusteredListener(this);
217             elanDpnInterfaceClusteredListener = ElanDpnInterfaceClusteredListener
218                     .getElanDpnInterfaceClusteredListener(this);
219             ElanClusterUtils.setElanServiceProvider(this);
220             this.elanL2GatewayProvider = new ElanL2GatewayProvider(this);
221             cacheElanInstanceListener = new CacheElanInstanceListener(this);
222             cacheElanInterfaceListener = new CacheElanInterfaceListener(this);
223             elanInterfaceManager.registerListener(LogicalDatastoreType.CONFIGURATION, broker);
224             elanInstanceManager.registerListener(LogicalDatastoreType.CONFIGURATION, broker);
225             notificationService.registerNotificationListener(elanSmacFlowEventListener);
226             notificationService.registerNotificationListener(elanPacketInHandler);
227             elanStatusMonitor.reportStatus("OPERATIONAL");
228         } catch (Exception e) {
229             logger.error("Error initializing services", e);
230             elanStatusMonitor.reportStatus("ERROR");
231         }
232     }
233
234     public void setIdManager(IdManagerService idManager) {
235         this.idManager = idManager;
236     }
237
238     public void setMdsalManager(IMdsalApiManager mdsalManager) {
239         this.mdsalManager = mdsalManager;
240     }
241
242     public void setInterfaceManager(IInterfaceManager interfaceManager) {
243         this.interfaceManager = interfaceManager;
244     }
245
246     public void setEntityOwnershipService(EntityOwnershipService entityOwnershipService) {
247         this.entityOwnershipService = entityOwnershipService;
248     }
249
250     public IInterfaceManager getInterfaceManager() {
251         return this.interfaceManager;
252     }
253
254     public IMdsalApiManager getMdsalManager() {
255         return mdsalManager;
256     }
257
258     public IITMProvider getItmManager() {
259         return itmManager;
260     }
261
262     public DataBroker getBroker() {
263         return broker;
264     }
265
266     public void setNotificationService(NotificationService notificationService) {
267         this.notificationService = notificationService;
268     }
269
270     public void setInterfaceManagerRpcService(OdlInterfaceRpcService interfaceManager) {
271         this.interfaceManagerRpcService = interfaceManager;
272     }
273
274     public OdlInterfaceRpcService getInterfaceManagerRpcService() {
275         return interfaceManagerRpcService;
276     }
277
278     public void setItmManager(IITMProvider itmManager) {
279         this.itmManager = itmManager;
280     }
281
282     public void setItmRpcService(ItmRpcService itmRpcService) {
283         this.itmRpcService = itmRpcService;
284     }
285
286     public ItmRpcService getItmRpcService() {
287         return itmRpcService;
288     }
289
290     public ElanInstanceManager getElanInstanceManager() {
291         return elanInstanceManager;
292     }
293
294     public ElanInterfaceManager getElanInterfaceManager() {
295         return elanInterfaceManager;
296     }
297
298     public EntityOwnershipService getEntityOwnershipService() {
299         return entityOwnershipService;
300     }
301
302     private void createIdPool() {
303         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder().setPoolName(ElanConstants.ELAN_ID_POOL_NAME)
304                 .setLow(ElanConstants.ELAN_ID_LOW_VALUE).setHigh(ElanConstants.ELAN_ID_HIGH_VALUE).build();
305         try {
306             Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
307             if ((result != null) && (result.get().isSuccessful())) {
308                 logger.debug("ELAN Id Pool is created successfully");
309             }
310         } catch (Exception e) {
311             logger.error("Failed to create ELAN Id pool {}", e);
312         }
313     }
314
315     @Override
316     public boolean createElanInstance(String elanInstanceName, long macTimeout, String description) {
317         ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName);
318         boolean isSuccess = true;
319         if (existingElanInstance != null) {
320             if (compareWithExistingElanInstance(existingElanInstance, macTimeout, description)) {
321                 logger.debug("Elan Instance is already present in the Operational DS {}", existingElanInstance);
322                 return true;
323             } else {
324                 ElanInstance updateElanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
325                         .setDescription(description).setMacTimeout(macTimeout)
326                         .setKey(new ElanInstanceKey(elanInstanceName)).build();
327                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
328                         ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName), updateElanInstance);
329                 logger.debug("Updating the Elan Instance {} with MAC TIME-OUT %l and Description %s ",
330                         updateElanInstance, macTimeout, description);
331             }
332         } else {
333             ElanInstance elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
334                     .setMacTimeout(macTimeout).setDescription(description).setKey(new ElanInstanceKey(elanInstanceName))
335                     .build();
336             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
337                     ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName), elanInstance);
338             logger.debug("Creating the new Elan Instance {}", elanInstance);
339         }
340         return isSuccess;
341     }
342
343     @Override
344     public boolean createEtreeInstance(String elanInstanceName, long macTimeout, String description) {
345         ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName);
346         boolean isSuccess = true;
347         if (existingElanInstance != null) {
348             if (compareWithExistingElanInstance(existingElanInstance, macTimeout, description)) {
349                 logger.warn("Etree Instance is already present in the Operational DS {}", existingElanInstance);
350                 return true;
351             } else {
352                 EtreeInstance etreeInstance = new EtreeInstanceBuilder().build();
353                 ElanInstance updateElanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
354                         .setDescription(description).setMacTimeout(macTimeout)
355                         .setKey(new ElanInstanceKey(elanInstanceName))
356                         .addAugmentation(EtreeInstance.class, etreeInstance).build();
357                 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
358                         ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName), updateElanInstance);
359                 logger.debug("Updating the Etree Instance {} with MAC TIME-OUT %l and Description %s ",
360                         updateElanInstance, macTimeout, description);
361             }
362         } else {
363             EtreeInstance etreeInstance = new EtreeInstanceBuilder().build();
364             ElanInstance elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
365                     .setMacTimeout(macTimeout).setDescription(description).setKey(new ElanInstanceKey(elanInstanceName))
366                     .addAugmentation(EtreeInstance.class, etreeInstance).build();
367             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
368                     ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName), elanInstance);
369             logger.debug("Creating the new Etree Instance {}", elanInstance);
370         }
371         return isSuccess;
372     }
373
374     public static boolean compareWithExistingElanInstance(ElanInstance existingElanInstance, long macTimeOut,
375             String description) {
376         boolean isEqual = false;
377         if (existingElanInstance.getMacTimeout() == macTimeOut
378                 && existingElanInstance.getDescription().equals(description)) {
379             isEqual = true;
380         }
381         return isEqual;
382     }
383
384     @Override
385     public void updateElanInstance(String elanInstanceName, long newMacTimout, String newDescription) {
386         createElanInstance(elanInstanceName, newMacTimout, newDescription);
387     }
388
389     @Override
390     public boolean deleteEtreeInstance(String etreeInstanceName) {
391         return deleteElanInstance(etreeInstanceName);
392     }
393
394     @Override
395     public boolean deleteElanInstance(String elanInstanceName) {
396         boolean isSuccess = false;
397         ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName);
398         if (existingElanInstance == null) {
399             logger.debug("Elan Instance is not present {}", existingElanInstance);
400             return isSuccess;
401         }
402         logger.debug("Deletion of the existing Elan Instance {}", existingElanInstance);
403         ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
404                 ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName));
405         isSuccess = true;
406         return isSuccess;
407     }
408
409     @Override
410     public void addEtreeInterface(String etreeInstanceName, String interfaceName, EtreeInterfaceType interfaceType,
411             List<String> staticMacAddresses, String description) {
412         ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(etreeInstanceName);
413         if (existingElanInstance != null && existingElanInstance.getAugmentation(EtreeInstance.class) != null) {
414             EtreeInterface etreeInterface = new EtreeInterfaceBuilder().setEtreeInterfaceType(interfaceType).build();
415             ElanInterface elanInterface;
416             if (staticMacAddresses == null) {
417                 elanInterface = new ElanInterfaceBuilder().setElanInstanceName(etreeInstanceName)
418                         .setDescription(description).setName(interfaceName).setKey(new ElanInterfaceKey(interfaceName))
419                         .addAugmentation(EtreeInterface.class, etreeInterface).build();
420             } else {
421                 elanInterface = new ElanInterfaceBuilder().setElanInstanceName(etreeInstanceName)
422                         .setDescription(description).setName(interfaceName)
423                         .setStaticMacEntries(getPhysAddress(staticMacAddresses))
424                         .setKey(new ElanInterfaceKey(interfaceName))
425                         .addAugmentation(EtreeInterface.class, etreeInterface).build();
426             }
427             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
428                     ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
429             logger.debug("Creating the new Etree Interface {}", elanInterface);
430         }
431     }
432
433     @Override
434     public void addElanInterface(String elanInstanceName, String interfaceName, List<String> staticMacAddresses,
435             String description) {
436         ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName);
437         if (existingElanInstance != null) {
438             ElanInterface elanInterface;
439             if (staticMacAddresses == null) {
440                 elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
441                         .setDescription(description).setName(interfaceName).setKey(new ElanInterfaceKey(interfaceName))
442                         .build();
443             } else {
444                 elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
445                         .setDescription(description).setName(interfaceName)
446                         .setStaticMacEntries(getPhysAddress(staticMacAddresses))
447                         .setKey(new ElanInterfaceKey(interfaceName)).build();
448             }
449             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
450                     ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
451             logger.debug("Creating the new ELan Interface {}", elanInterface);
452         }
453     }
454
455     @Override
456     public void updateElanInterface(String elanInstanceName, String interfaceName,
457             List<String> updatedStaticMacAddresses, String newDescription) {
458         ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
459         if (existingElanInterface == null) {
460             return;
461         }
462         List<PhysAddress> existingMacAddress = existingElanInterface.getStaticMacEntries();
463         List<PhysAddress> updatedMacAddresses = getPhysAddress(updatedStaticMacAddresses);
464         List<PhysAddress> updatedPhysAddress = getUpdatedPhyAddress(existingMacAddress, updatedMacAddresses);
465         if (updatedPhysAddress.size() > 0) {
466             logger.debug("updating the ElanInterface with new Mac Entries {}", updatedStaticMacAddresses);
467             ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
468                     .setName(interfaceName).setDescription(newDescription).setStaticMacEntries(updatedPhysAddress)
469                     .setKey(new ElanInterfaceKey(interfaceName)).build();
470             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
471                     ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
472         }
473     }
474
475     @Override
476     public void deleteEtreeInterface(String elanInstanceName, String interfaceName) {
477         deleteElanInterface(elanInstanceName, interfaceName);
478         logger.debug("deleting the Etree Interface {}", interfaceName);
479     }
480
481     @Override
482     public void deleteElanInterface(String elanInstanceName, String interfaceName) {
483         ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
484         if (existingElanInterface != null) {
485             ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
486                     ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName));
487             logger.debug("deleting the Elan Interface {}", existingElanInterface);
488         }
489     }
490
491     @Override
492     public void addStaticMacAddress(String elanInstanceName, String interfaceName, String macAddress) {
493         ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
494         PhysAddress updateStaticMacAddress = new PhysAddress(macAddress);
495         if (existingElanInterface != null) {
496             List<PhysAddress> existingMacAddress = existingElanInterface.getStaticMacEntries();
497             if (existingMacAddress.contains(updateStaticMacAddress)) {
498                 return;
499             }
500             existingMacAddress.add(updateStaticMacAddress);
501             ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
502                     .setName(interfaceName).setStaticMacEntries(existingMacAddress)
503                     .setDescription(existingElanInterface.getDescription()).setKey(new ElanInterfaceKey(interfaceName))
504                     .build();
505             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
506                     ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
507         }
508     }
509
510     @Override
511     public void deleteStaticMacAddress(String elanInstanceName, String interfaceName, String macAddress)
512             throws MacNotFoundException {
513         ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
514         PhysAddress physAddress = new PhysAddress(macAddress);
515         if (existingElanInterface == null) {
516             return;
517         }
518         List<PhysAddress> existingMacAddress = existingElanInterface.getStaticMacEntries();
519         if (existingMacAddress.contains(physAddress)) {
520             existingMacAddress.remove(physAddress);
521             ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
522                     .setName(interfaceName).setStaticMacEntries(existingMacAddress)
523                     .setDescription(existingElanInterface.getDescription()).setKey(new ElanInterfaceKey(interfaceName))
524                     .build();
525             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
526                     ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
527         } else {
528             throw new MacNotFoundException("Mac Not Found Exception");
529         }
530     }
531
532     @Override
533     public Collection<MacEntry> getElanMacTable(String elanInstanceName) {
534         Elan elanInfo = ElanUtils.getElanByName(elanInstanceName);
535         List<MacEntry> macAddress = new ArrayList<>();
536         if (elanInfo == null) {
537             return macAddress;
538         }
539         List<String> elanInterfaces = elanInfo.getElanInterfaces();
540         if (elanInterfaces != null && elanInterfaces.size() > 0) {
541             for (String elanInterface : elanInterfaces) {
542                 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
543                 if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null
544                         && elanInterfaceMac.getMacEntry().size() > 0) {
545                     macAddress.addAll(elanInterfaceMac.getMacEntry());
546                 }
547             }
548         }
549         return macAddress;
550     }
551
552     @Override
553     public void flushMACTable(String elanInstanceName) {
554         Elan elanInfo = ElanUtils.getElanByName(elanInstanceName);
555         if (elanInfo == null) {
556             return;
557         }
558         List<String> elanInterfaces = elanInfo.getElanInterfaces();
559         if (elanInterfaces == null || elanInterfaces.isEmpty()) {
560             return;
561         }
562         for (String elanInterface : elanInterfaces) {
563             ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
564             if (elanInterfaceMac.getMacEntry() != null && elanInterfaceMac.getMacEntry().size() > 0) {
565                 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
566                 for (MacEntry macEntry : macEntries) {
567                     try {
568                         deleteStaticMacAddress(elanInstanceName, elanInterface, macEntry.getMacAddress().getValue());
569                     } catch (MacNotFoundException e) {
570                         logger.error("Mac Not Found Exception {}", e);
571                         e.printStackTrace();
572                     }
573                 }
574             }
575         }
576
577     }
578
579     @Override
580     public void close() throws Exception {
581         this.elanInstanceManager.close();
582         this.elanL2GatewayProvider.close();
583         this.cacheElanInstanceListener.close();
584         this.cacheElanInterfaceListener.close();
585     }
586
587     public static List<PhysAddress> getPhysAddress(List<String> macAddress) {
588         List<PhysAddress> physAddresses = new ArrayList<>();
589         for (String mac : macAddress) {
590             physAddresses.add(new PhysAddress(mac));
591         }
592         return physAddresses;
593     }
594
595     public List<PhysAddress> getUpdatedPhyAddress(List<PhysAddress> originalAddresses,
596             List<PhysAddress> updatePhyAddresses) {
597         if (updatePhyAddresses != null && !updatePhyAddresses.isEmpty()) {
598             List<PhysAddress> existingClonedPhyAddress = new ArrayList<>();
599             if (originalAddresses != null && !originalAddresses.isEmpty()) {
600                 existingClonedPhyAddress.addAll(0, originalAddresses);
601                 originalAddresses.removeAll(updatePhyAddresses);
602                 updatePhyAddresses.removeAll(existingClonedPhyAddress);
603             }
604         }
605         return updatePhyAddresses;
606     }
607
608     @Override
609     public ElanInstance getElanInstance(String elanName) {
610         return ElanUtils.getElanInstanceByName(elanName);
611     }
612
613     @Override
614     public List<ElanInstance> getElanInstances() {
615         List<ElanInstance> elanList = new ArrayList<>();
616         InstanceIdentifier<ElanInstances> elanInstancesIdentifier = InstanceIdentifier.builder(ElanInstances.class)
617                 .build();
618         Optional<ElanInstances> elansOptional = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
619                 elanInstancesIdentifier);
620         if (elansOptional.isPresent()) {
621             elanList.addAll(elansOptional.get().getElanInstance());
622         }
623         return elanList;
624     }
625
626     @Override
627     public List<String> getElanInterfaces(String elanInstanceName) {
628         List<String> elanInterfaces = new ArrayList<>();
629         InstanceIdentifier<ElanInterfaces> elanInterfacesIdentifier = InstanceIdentifier.builder(ElanInterfaces.class)
630                 .build();
631         Optional<ElanInterfaces> elanInterfacesOptional = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
632                 elanInterfacesIdentifier);
633         if (!elanInterfacesOptional.isPresent()) {
634             return elanInterfaces;
635         }
636         List<ElanInterface> elanInterfaceList = elanInterfacesOptional.get().getElanInterface();
637         for (ElanInterface elanInterface : elanInterfaceList) {
638             if (elanInterface.getElanInstanceName().equals(elanInstanceName)) {
639                 elanInterfaces.add(elanInterface.getName());
640             }
641         }
642         return elanInterfaces;
643     }
644
645     public boolean getGenerateIntBridgeMac() {
646         return generateIntBridgeMac;
647     }
648
649     public void setGenerateIntBridgeMac(boolean generateIntBridgeMac) {
650         this.generateIntBridgeMac = generateIntBridgeMac;
651     }
652
653     @Override
654     public void createExternalElanNetworks(Node node) {
655         handleExternalElanNetworks(node, new BiFunction<ElanInstance, String, Void>() {
656
657             @Override
658             public Void apply(ElanInstance elanInstance, String interfaceName) {
659                 createExternalElanNetwork(elanInstance, interfaceName);
660                 return null;
661             }
662         });
663     }
664
665     @Override
666     public void createExternalElanNetwork(ElanInstance elanInstance) {
667         handleExternalElanNetwork(elanInstance, new BiFunction<ElanInstance, String, Void>() {
668
669             @Override
670             public Void apply(ElanInstance elanInstance, String interfaceName) {
671                 createExternalElanNetwork(elanInstance, interfaceName);
672                 return null;
673             }
674
675         });
676     }
677
678     @Override
679     public void deleteExternalElanNetworks(Node node) {
680         handleExternalElanNetworks(node, new BiFunction<ElanInstance, String, Void>() {
681
682             @Override
683             public Void apply(ElanInstance elanInstance, String interfaceName) {
684                 deleteExternalElanNetwork(elanInstance, interfaceName);
685                 return null;
686             }
687         });
688     }
689
690     @Override
691     public void deleteExternalElanNetwork(ElanInstance elanInstance) {
692         handleExternalElanNetwork(elanInstance, new BiFunction<ElanInstance, String, Void>() {
693
694             @Override
695             public Void apply(ElanInstance elanInstance, String interfaceName) {
696                 deleteExternalElanNetwork(elanInstance, interfaceName);
697                 return null;
698             }
699
700         });
701     }
702
703     @Override
704     public void updateExternalElanNetworks(Node origNode, Node updatedNode) {
705         if (!bridgeMgr.isIntegrationBridge(updatedNode)) {
706             return;
707         }
708
709         List<ElanInstance> elanInstances = getElanInstances();
710         if (elanInstances == null || elanInstances.isEmpty()) {
711             logger.trace("No ELAN instances found");
712             return;
713         }
714
715         Optional<Map<String, String>> origProviderMapOpt = bridgeMgr.getOpenvswitchOtherConfigMap(origNode,
716                 ElanBridgeManager.PROVIDER_MAPPINGS_KEY);
717         Optional<Map<String, String>> updatedProviderMapOpt = bridgeMgr.getOpenvswitchOtherConfigMap(updatedNode,
718                 ElanBridgeManager.PROVIDER_MAPPINGS_KEY);
719         Map<String, String> origProviderMappping = origProviderMapOpt.or(Collections.emptyMap());
720         Map<String, String> updatedProviderMappping = updatedProviderMapOpt.or(Collections.emptyMap());
721
722         for (ElanInstance elanInstance : elanInstances) {
723             String physicalNetworkName = elanInstance.getPhysicalNetworkName();
724             if (physicalNetworkName != null) {
725                 String origPortName = origProviderMappping.get(physicalNetworkName);
726                 String updatedPortName = updatedProviderMappping.get(physicalNetworkName);
727                 if (origPortName != null && !origPortName.equals(updatedPortName)) {
728                     deleteExternalElanNetwork(elanInstance, getExtInterfaceName(origNode, physicalNetworkName));
729                 }
730                 if (updatedPortName != null && !updatedPortName.equals(origPortName)) {
731                     createExternalElanNetwork(elanInstance, getExtInterfaceName(updatedNode, updatedPortName));
732                 }
733             }
734         }
735     }
736
737     private void createExternalElanNetwork(ElanInstance elanInstance, String interfaceName) {
738         if (interfaceName == null) {
739             logger.trace("No physial interface is attached to {}", elanInstance.getPhysicalNetworkName());
740             return;
741         }
742
743         String elanInterfaceName = createIetfInterfaces(elanInstance, interfaceName);
744         addElanInterface(elanInstance.getElanInstanceName(), elanInterfaceName, null, null);
745     }
746
747     private void deleteExternalElanNetwork(ElanInstance elanInstance, String interfaceName) {
748         if (interfaceName == null) {
749             logger.trace("No physial interface is attached to {}", elanInstance.getPhysicalNetworkName());
750             return;
751         }
752
753         String elanInstanceName = elanInstance.getElanInstanceName();
754         for (String elanInterface : getExternalElanInterfaces(elanInstanceName)) {
755             if (elanInterface.startsWith(interfaceName)) {
756                 deleteIetfInterface(elanInterface);
757                 deleteElanInterface(elanInstanceName, elanInterface);
758             }
759         }
760     }
761
762     @Override
763     public Collection<String> getExternalElanInterfaces(String elanInstanceName) {
764         List<String> elanInterfaces = getElanInterfaces(elanInstanceName);
765         if (elanInterfaces == null || elanInterfaces.isEmpty()) {
766             logger.trace("No ELAN interfaces defined for {}", elanInstanceName);
767             return Collections.emptySet();
768         }
769
770         Set<String> externalElanInterfaces = new HashSet<>();
771         for (String elanInterface : elanInterfaces) {
772             if (ElanUtils.isExternal(elanInterface)) {
773                 externalElanInterfaces.add(elanInterface);
774             }
775         }
776
777         return externalElanInterfaces;
778     }
779
780     /**
781      * Create ietf-interfaces based on the ELAN segment type.<br>
782      * For segment type flat - create transparent interface pointing to the
783      * patch-port attached to the physnet port.<br>
784      * For segment type vlan - create trunk interface pointing to the patch-port
785      * attached to the physnet port + trunk-member interface pointing to the
786      * trunk interface.
787      *
788      * @param elanInstance
789      *            ELAN instance
790      * @param parentRef
791      *            parent interface name
792      * @return the name of the interface to be added to the ELAN instance i.e.
793      *         trunk-member name for vlan network and transparent for flat
794      *         network or null otherwise
795      */
796     private String createIetfInterfaces(ElanInstance elanInstance, String parentRef) {
797         String interfaceName = null;
798
799         try {
800             if (ElanUtils.isFlat(elanInstance)) {
801                 interfaceName = parentRef + IfmConstants.OF_URI_SEPARATOR + "flat";
802                 interfaceManager.createVLANInterface(interfaceName, parentRef, null, null, null,
803                         IfL2vlan.L2vlanMode.Transparent, true);
804             } else if (ElanUtils.isVlan(elanInstance)) {
805                 String trunkName = parentRef + IfmConstants.OF_URI_SEPARATOR + "trunk";
806                 interfaceManager.createVLANInterface(interfaceName, parentRef, null, null, null,
807                         IfL2vlan.L2vlanMode.Trunk, true);
808                 Long segmentationId = elanInstance.getSegmentationId();
809                 interfaceName = parentRef + IfmConstants.OF_URI_SEPARATOR + segmentationId;
810                 interfaceManager.createVLANInterface(interfaceName, trunkName, null, segmentationId.intValue(), null,
811                         IfL2vlan.L2vlanMode.TrunkMember, true);
812             }
813         } catch (InterfaceAlreadyExistsException e) {
814             logger.trace("Interface {} was already created", interfaceName);
815         }
816
817         return interfaceName;
818     }
819
820     private void deleteIetfInterface(String interfaceName) {
821         InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
822         InstanceIdentifier<Interface> interfaceInstanceIdentifier = InstanceIdentifier.builder(Interfaces.class)
823                 .child(Interface.class, interfaceKey).build();
824         MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
825         logger.debug("Deleting IETF interface {}", interfaceName);
826     }
827
828     private String getExtInterfaceName(Node node, String physicalNetworkName) {
829         if (physicalNetworkName == null) {
830             return null;
831         }
832
833         String providerMappingValue = bridgeMgr.getProviderMappingValue(node, physicalNetworkName);
834         if (providerMappingValue == null) {
835             logger.trace("No provider mapping found for physicalNetworkName {} node {}", physicalNetworkName,
836                     node.getNodeId().getValue());
837             return null;
838         }
839
840         return bridgeMgr.southboundUtils.getDataPathId(node) + IfmConstants.OF_URI_SEPARATOR
841                 + bridgeMgr.getIntBridgePortNameFor(node, providerMappingValue);
842     }
843
844     private void handleExternalElanNetworks(Node node, BiFunction<ElanInstance, String, Void> function) {
845         if (!bridgeMgr.isIntegrationBridge(node)) {
846             return;
847         }
848
849         List<ElanInstance> elanInstances = getElanInstances();
850         if (elanInstances == null || elanInstances.isEmpty()) {
851             logger.trace("No ELAN instances found");
852             return;
853         }
854
855         for (ElanInstance elanInstance : elanInstances) {
856             String interfaceName = getExtInterfaceName(node, elanInstance.getPhysicalNetworkName());
857             if (interfaceName != null) {
858                 function.apply(elanInstance, interfaceName);
859             }
860         }
861     }
862
863     private void handleExternalElanNetwork(ElanInstance elanInstance, BiFunction<ElanInstance, String, Void> function) {
864         String elanInstanceName = elanInstance.getElanInstanceName();
865         if (elanInstance.getPhysicalNetworkName() == null) {
866             logger.trace("No physical network attached to {}", elanInstanceName);
867             return;
868         }
869
870         List<Node> nodes = bridgeMgr.southboundUtils.getOvsdbNodes();
871         if (nodes == null || nodes.isEmpty()) {
872             logger.trace("No OVS nodes found while creating external network for ELAN {}",
873                     elanInstance.getElanInstanceName());
874             return;
875         }
876
877         for (Node node : nodes) {
878             if (bridgeMgr.isIntegrationBridge(node)) {
879                 String interfaceName = getExtInterfaceName(node, elanInstance.getPhysicalNetworkName());
880                 function.apply(elanInstance, interfaceName);
881             }
882         }
883     }
884
885 }