ELAN FT Support for BE
[vpnservice.git] / elanmanager / elanmanager-impl / src / main / java / org / opendaylight / vpnservice / 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 package org.opendaylight.vpnservice.elan.internal;
9
10 import com.google.common.base.Optional;
11 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
12 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
13 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
14 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
15 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
16 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
17 import org.opendaylight.elanmanager.api.IElanService;
18 import org.opendaylight.vpnservice.elan.statisitcs.ElanStatisticsImpl;
19 import org.opendaylight.vpnservice.elan.utils.ElanConstants;
20 import org.opendaylight.vpnservice.elan.utils.ElanUtils;
21 import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
22 import org.opendaylight.vpnservice.itm.api.IITMProvider;
23 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
24 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInstances;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInterfaces;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterfaceBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterfaceKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.Elan;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntry;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.statistics.rev150824.ElanStatisticsService;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInputBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.opendaylight.yangtools.yang.common.RpcResult;
45 import org.opendaylight.elanmanager.exceptions.MacNotFoundException;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 import java.util.ArrayList;
50 import java.util.Collection;
51 import java.util.List;
52 import java.util.concurrent.Future;
53
54 public class ElanServiceProvider implements BindingAwareProvider, IElanService, AutoCloseable {
55
56     private IdManagerService idManager;
57     private IMdsalApiManager mdsalManager;
58     private IInterfaceManager interfaceManager;
59     private OdlInterfaceRpcService interfaceManagerRpcService;
60     private ElanInstanceManager elanInstanceManager;
61     private ElanForwardingEntriesHandler elanForwardingEntriesHandler;
62     private ElanInterfaceManager elanInterfaceManager;
63     private ElanPacketInHandler elanPacketInHandler;
64     private ElanSmacFlowEventListener elanSmacFlowEventListener;
65     private ElanNodeListener elanNodeListener;
66     private NotificationService notificationService;
67     private RpcProviderRegistry rpcProviderRegistry;
68
69     public ElanServiceProvider(RpcProviderRegistry rpcRegistry) {
70         rpcProviderRegistry = rpcRegistry;
71     }
72
73     //private ElanInterfaceEventListener elanInterfaceEventListener;
74     private ElanItmEventListener elanItmEventListener;
75     private IITMProvider itmManager;
76     private DataBroker broker;
77
78     private static final Logger logger = LoggerFactory.getLogger(ElanServiceProvider.class);
79
80     @Override
81     public void onSessionInitiated(ProviderContext session) {
82         createIdPool();
83         broker = session.getSALService(DataBroker.class);
84
85         elanForwardingEntriesHandler = new ElanForwardingEntriesHandler(broker, mdsalManager);
86         elanForwardingEntriesHandler.setIITMManager(itmManager);
87
88         elanInterfaceManager = ElanInterfaceManager.getElanInterfaceManager();
89         elanInterfaceManager.setInterfaceManager(interfaceManager);
90         elanInterfaceManager.setIdManager(idManager);
91         elanInterfaceManager.setMdSalApiManager(mdsalManager);
92         elanInterfaceManager.setDataBroker(broker);
93         elanInterfaceManager.setIITMManager(itmManager);
94         elanInterfaceManager.registerListener();
95         elanInterfaceManager.setInterfaceManagerRpcService(interfaceManagerRpcService);
96         elanInterfaceManager.setElanForwardingEntriesHandler(elanForwardingEntriesHandler);
97
98         elanInstanceManager = ElanInstanceManager.getElanInstanceManager();
99         elanInstanceManager.setDataBroker(broker);
100         elanInstanceManager.setIdManager(idManager);
101         elanInstanceManager.setElanInterfaceManager(elanInterfaceManager);
102         elanInstanceManager.registerListener();
103
104         elanNodeListener = new ElanNodeListener(broker, mdsalManager);
105
106         elanPacketInHandler = new ElanPacketInHandler(broker);
107         elanPacketInHandler.setInterfaceManager(interfaceManager);
108         notificationService.registerNotificationListener(elanPacketInHandler);
109
110         elanSmacFlowEventListener = new ElanSmacFlowEventListener(broker);
111         elanSmacFlowEventListener.setMdSalApiManager(mdsalManager);
112         elanSmacFlowEventListener.setInterfaceManager(interfaceManager);
113         elanSmacFlowEventListener.setIITMManager(itmManager);
114         elanSmacFlowEventListener.setSalFlowService(session.getRpcService(SalFlowService.class));
115         notificationService.registerNotificationListener(elanSmacFlowEventListener);
116
117         // Initialize statistics rpc provider for elan
118         ElanStatisticsService interfaceStatsService = new ElanStatisticsImpl(broker, interfaceManager, mdsalManager);
119         rpcProviderRegistry.addRpcImplementation(ElanStatisticsService.class, interfaceStatsService);
120
121         ElanUtils.setElanServiceProvider(this);
122     }
123
124     public void setIdManager(IdManagerService idManager) {
125         this.idManager = idManager;
126     }
127
128     public void setMdsalManager(IMdsalApiManager mdsalManager) {
129         this.mdsalManager = mdsalManager;
130     }
131
132     public void setInterfaceManager(IInterfaceManager interfaceManager) {
133         this.interfaceManager = interfaceManager;
134     }
135
136     public IMdsalApiManager getMdsalManager() {
137         return mdsalManager;
138     }
139
140     public IITMProvider getItmManager() {
141         return itmManager;
142     }
143
144     public DataBroker getBroker() {
145         return broker;
146     }
147
148     public void setNotificationService(NotificationService notificationService) {
149         this.notificationService = notificationService;
150     }
151
152     public void setInterfaceManagerRpcService(OdlInterfaceRpcService interfaceManager) {
153         this.interfaceManagerRpcService = interfaceManager;
154     }
155
156     public OdlInterfaceRpcService getInterfaceManagerRpcService() {
157         return interfaceManagerRpcService;
158     }
159
160     public void setItmManager(IITMProvider itmManager) {
161         this.itmManager = itmManager;
162     }
163
164     private void createIdPool() {
165         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
166             .setPoolName(ElanConstants.ELAN_ID_POOL_NAME).setLow(ElanConstants.ELAN_ID_LOW_VALUE).setHigh(ElanConstants.ELAN_ID_HIGH_VALUE)
167             .build();
168         try {
169            Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
170            if ((result != null) && (result.get().isSuccessful())) {
171                logger.debug("ELAN Id Pool is created successfully");
172             }
173         } catch (Exception e) {
174             logger.error("Failed to create ELAN Id pool {}", e);
175         }
176     }
177
178     @Override
179     public boolean createElanInstance(String elanInstanceName, long macTimeout, String description) {
180         ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName);
181         boolean isSuccess = true;
182         if(existingElanInstance != null) {
183            if(compareWithExistingElanInstance(existingElanInstance, macTimeout, description)) {
184                logger.debug("Elan Instance is already present in the Operational DS {}", existingElanInstance);
185                return true;
186            } else {
187                ElanInstance updateElanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setDescription(description).setMacTimeout(macTimeout).setKey(new ElanInstanceKey(elanInstanceName)).build();
188                MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName), updateElanInstance);
189                logger.debug("Updating the Elan Instance {} with MAC TIME-OUT %l and Description %s ", updateElanInstance, macTimeout, description);
190            }
191         } else {
192             ElanInstance elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setMacTimeout(macTimeout).setDescription(description).setKey(new ElanInstanceKey(elanInstanceName)).build();
193             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInstanceIdentifier(elanInstanceName), elanInstance);
194             logger.debug("Creating the new Elan Instance {}", elanInstance);
195         }
196         return isSuccess;
197     }
198
199     public static boolean compareWithExistingElanInstance(ElanInstance existingElanInstance, long macTimeOut, String description) {
200         boolean isEqual = false;
201         if(existingElanInstance.getMacTimeout() == macTimeOut && existingElanInstance.getDescription().equals(description)) {
202             isEqual = true;
203         }
204         return isEqual;
205     }
206     @Override
207     public void updateElanInstance(String elanInstanceName, long newMacTimout, String newDescription) {
208         createElanInstance(elanInstanceName, newMacTimout, newDescription);
209     }
210
211     @Override
212     public boolean deleteElanInstance(String elanInstanceName) {
213         boolean isSuccess = false;
214         ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName);
215         if(existingElanInstance == null) {
216             logger.debug("Elan Instance is not present {}" , existingElanInstance);
217             return isSuccess;
218         }
219         logger.debug("Deletion of the existing Elan Instance {}", existingElanInstance);
220         ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInstanceIdentifier(elanInstanceName));
221         isSuccess = true;
222         return isSuccess;
223     }
224
225     @Override
226     public void addElanInterface(String elanInstanceName, String interfaceName, List<String> staticMacAddresses, String description) {
227           ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName);
228           if(existingElanInstance != null) {
229               ElanInterface elanInterface;
230               if(staticMacAddresses == null) {
231                   elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName).setDescription(description).setName(interfaceName).setKey(new ElanInterfaceKey(interfaceName)).build();
232               } else {
233                   elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName).setDescription(description).setName(interfaceName).setStaticMacEntries(getPhysAddress(staticMacAddresses)).setKey(new ElanInterfaceKey(interfaceName)).build();
234               }
235               MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
236               logger.debug("Creating the new ELan Interface {}", elanInterface);
237           }
238
239     }
240
241     @Override
242     public void updateElanInterface(String elanInstanceName, String interfaceName, List<String> updatedStaticMacAddresses, String newDescription) {
243         ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
244         if (existingElanInterface == null) {
245             return;
246         }
247         List<PhysAddress> existingMacAddress = existingElanInterface.getStaticMacEntries();
248         List<PhysAddress> updatedMacAddresses = getPhysAddress(updatedStaticMacAddresses);
249         List<PhysAddress> updatedPhysAddress = getUpdatedPhyAddress(existingMacAddress, updatedMacAddresses);
250         if(updatedPhysAddress.size() > 0) {
251             logger.debug("updating the ElanInterface with new Mac Entries {}", updatedStaticMacAddresses);
252             ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName).setName(interfaceName).setDescription(newDescription).setStaticMacEntries(updatedPhysAddress).setKey(new ElanInterfaceKey(interfaceName)).build();
253             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
254         }
255     }
256
257     @Override
258     public void deleteElanInterface(String elanInstanceName, String interfaceName) {
259         ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
260         if(existingElanInterface != null) {
261             ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName));
262             logger.debug("deleting the Elan Interface {}", existingElanInterface);
263         }
264     }
265
266     @Override
267     public void addStaticMacAddress(String elanInstanceName, String interfaceName, String macAddress) {
268         ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
269         PhysAddress updateStaticMacAddress = new PhysAddress(macAddress);
270         if (existingElanInterface != null) {
271             List<PhysAddress> existingMacAddress = existingElanInterface.getStaticMacEntries();
272             if(existingMacAddress.contains(updateStaticMacAddress)) {
273                 return;
274             }
275             existingMacAddress.add(updateStaticMacAddress);
276             ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName).setName(interfaceName).setStaticMacEntries(existingMacAddress).setDescription(existingElanInterface.getDescription()).setKey(new ElanInterfaceKey(interfaceName)).build();
277             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
278         }
279     }
280
281     @Override
282     public void deleteStaticMacAddress(String elanInstanceName, String interfaceName, String macAddress) throws MacNotFoundException {
283            ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
284         PhysAddress physAddress = new PhysAddress(macAddress);
285         if(existingElanInterface == null) {
286             return;
287         }
288         List<PhysAddress> existingMacAddress = existingElanInterface.getStaticMacEntries();
289         if(existingMacAddress.contains(physAddress)) {
290             existingMacAddress.remove(physAddress);
291             ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName).setName(interfaceName).setStaticMacEntries(existingMacAddress).setDescription(existingElanInterface.getDescription()).setKey(new ElanInterfaceKey(interfaceName)).build();
292             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
293         } else {
294             throw new MacNotFoundException("Mac Not Found Exception");
295         }
296     }
297
298     @Override
299     public Collection<MacEntry> getElanMacTable(String elanInstanceName) {
300         Elan elanInfo = ElanUtils.getElanByName(elanInstanceName);
301         List<MacEntry> macAddress = new ArrayList<>();
302         if(elanInfo == null) {
303             return macAddress;
304         }
305        List<String> elanInterfaces =  elanInfo.getElanInterfaces();
306         if(elanInterfaces != null && elanInterfaces.size() > 0) {
307             for(String elanInterface : elanInterfaces) {
308                 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
309                 if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null && elanInterfaceMac.getMacEntry().size() > 0){
310                     macAddress.addAll(elanInterfaceMac.getMacEntry());
311                 }
312             }
313         }
314        return macAddress;
315     }
316
317     @Override
318     public void flushMACTable(String elanInstanceName) {
319         Elan elanInfo = ElanUtils.getElanByName(elanInstanceName);
320         if(elanInfo == null) {
321             return;
322         }
323         List<String> elanInterfaces = elanInfo.getElanInterfaces();
324         if (elanInterfaces == null || elanInterfaces.isEmpty()) {
325             return;
326         }
327         for (String elanInterface : elanInterfaces) {
328             ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
329             if (elanInterfaceMac.getMacEntry() != null && elanInterfaceMac.getMacEntry().size() > 0) {
330                 List<MacEntry> macEntries =  elanInterfaceMac.getMacEntry();
331                 for(MacEntry macEntry : macEntries) {
332                     try {
333                         deleteStaticMacAddress(elanInstanceName, elanInterface, macEntry.getMacAddress().getValue());
334                     } catch (MacNotFoundException e) {
335                         logger.error("Mac Not Found Exception {}", e);
336                         e.printStackTrace();
337                     }
338                 }
339             }
340         }
341
342     }
343
344     @Override
345     public void close() throws Exception {
346         elanInstanceManager.close();
347     }
348
349     public static List<PhysAddress> getPhysAddress(List<String> macAddress) {
350         List<PhysAddress> physAddresses = new ArrayList<>();
351         for(String mac : macAddress) {
352             physAddresses.add(new PhysAddress(mac));
353         }
354         return physAddresses;
355     }
356
357
358     public List<PhysAddress> getUpdatedPhyAddress(List<PhysAddress> originalAddresses, List<PhysAddress> updatePhyAddresses) {
359         if(updatePhyAddresses != null && !updatePhyAddresses.isEmpty()) {
360             List<PhysAddress> existingClonedPhyAddress = new ArrayList<>();
361             if (originalAddresses != null && !originalAddresses.isEmpty()) {
362                 existingClonedPhyAddress.addAll(0, originalAddresses);
363                 originalAddresses.removeAll(updatePhyAddresses);
364                 updatePhyAddresses.removeAll(existingClonedPhyAddress);
365             }
366         }
367         return updatePhyAddresses;
368     }
369
370     @Override
371     public ElanInstance getElanInstance(String elanName) {
372         return ElanUtils.getElanInstanceByName(elanName);
373     }
374
375     @Override
376     public List<ElanInstance> getElanInstances() {
377         List<ElanInstance> elanList = new ArrayList<ElanInstance>();
378         InstanceIdentifier<ElanInstances> elanInstancesIdentifier =  InstanceIdentifier.builder(ElanInstances.class).build();
379         Optional<ElanInstances> elansOptional  = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanInstancesIdentifier);
380         if(elansOptional.isPresent()) {
381             elanList.addAll(elansOptional.get().getElanInstance());
382         }
383         return elanList;
384     }
385
386     @Override
387     public List<String> getElanInterfaces(String elanInstanceName) {
388         List<String> elanInterfaces = new ArrayList<>();
389         InstanceIdentifier<ElanInterfaces> elanInterfacesIdentifier =  InstanceIdentifier.builder(ElanInterfaces.class).build();
390         Optional<ElanInterfaces> elanInterfacesOptional  = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfacesIdentifier);
391         if(!elanInterfacesOptional.isPresent()) {
392              return elanInterfaces;
393         }
394         List<ElanInterface> elanInterfaceList = elanInterfacesOptional.get().getElanInterface();
395         for(ElanInterface elanInterface : elanInterfaceList) {
396             if(elanInterface.getElanInstanceName().equals(elanInstanceName)) {
397                 elanInterfaces.add(elanInterface.getName());
398             }
399         }
400         return elanInterfaces;
401     }
402 }