2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.vpnservice.elan.internal;
10 import com.google.common.base.Optional;
11 import com.google.common.collect.Maps;
12 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
13 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
14 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.vpnservice.elan.utils.ElanConstants;
17 import org.opendaylight.vpnservice.elan.utils.ElanUtils;
18 import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
19 import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo.InterfaceType;
20 import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
22 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
23 import org.opendaylight.vpnservice.itm.globals.ITMConstants;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
30 import org.opendaylight.vpnservice.mdsalutil.*;
31 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanDpnInterfaces;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanForwardingTables;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInterfaces;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.forwarding.tables.MacTable;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.forwarding.tables.MacTableKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.Elan;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.ElanBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.ElanKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntry;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
57 import org.opendaylight.yangtools.concepts.ListenerRegistration;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
62 import java.math.BigInteger;
64 import java.util.concurrent.ConcurrentHashMap;
65 import java.util.concurrent.ConcurrentLinkedQueue;
68 public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterface> implements AutoCloseable {
70 private static ElanInterfaceManager elanInterfaceManager = new ElanInterfaceManager();
71 private ListenerRegistration<DataChangeListener> elanInterfaceListenerRegistration;
72 private ListenerRegistration<DataChangeListener> itmInterfaceListenerRegistration;
73 private OdlInterfaceRpcService interfaceManagerRpcService;
74 private DataBroker broker;
75 private IMdsalApiManager mdsalManager;
76 private IInterfaceManager interfaceManager;
77 private IdManagerService idManager;
79 private ElanForwardingEntriesHandler elanForwardingEntriesHandler;
80 private Map<String, ConcurrentLinkedQueue<ElanInterface>> unProcessedElanInterfaces =
81 new ConcurrentHashMap<String, ConcurrentLinkedQueue<ElanInterface>> ();
83 private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceManager.class);
85 public ElanInterfaceManager() {
86 super(ElanInterface.class);
89 public static ElanInterfaceManager getElanInterfaceManager() {
90 return elanInterfaceManager;
93 public void setMdSalApiManager(IMdsalApiManager mdsalManager) {
94 this.mdsalManager = mdsalManager;
97 public void setInterfaceManagerRpcService(OdlInterfaceRpcService ifManager) {
98 this.interfaceManagerRpcService = ifManager;
101 public void setElanForwardingEntriesHandler(ElanForwardingEntriesHandler elanForwardingEntriesHandler) {
102 this.elanForwardingEntriesHandler = elanForwardingEntriesHandler;
105 public void setInterfaceManager(IInterfaceManager interfaceManager) {
106 this.interfaceManager = interfaceManager;
109 public void setDataBroker(DataBroker broker) {
110 this.broker = broker;
114 public void close() throws Exception {
115 if (elanInterfaceListenerRegistration != null) {
117 elanInterfaceListenerRegistration.close();
118 } catch (final Exception e) {
119 logger.error("Error when cleaning up DataChangeListener.", e);
121 elanInterfaceListenerRegistration = null;
125 public void registerListener() {
127 elanInterfaceListenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
128 getElanInterfaceWildcardPath(), ElanInterfaceManager.this, DataChangeScope.SUBTREE);
129 } catch (final Exception e) {
130 logger.error("ELAN Interface DataChange listener registration failed !", e);
131 throw new IllegalStateException("ELAN Interface registration Listener failed.", e);
135 private InstanceIdentifier<?> getElanInterfaceWildcardPath() {
136 return InstanceIdentifier.create(ElanInterfaces.class).child(ElanInterface.class);
139 public void setIdManager(IdManagerService idManager) {
140 this.idManager = idManager;
144 protected void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
145 String interfaceName = del.getName();
146 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(del.getElanInstanceName());
147 removeElanInterface(elanInfo, interfaceName);
150 public void removeElanService(ElanInterface del, InterfaceInfo interfaceInfo) {
151 ElanInstance elanInstance = ElanUtils.getElanInstanceByName(del.getElanInstanceName());
152 String interfaceName = del.getName();
153 removeElanInterface(elanInstance, interfaceInfo);
154 unbindService(elanInstance, interfaceName);
157 public void removeElanInterface(ElanInstance elanInfo, String interfaceName) {
158 String elanName = elanInfo.getElanInstanceName();
159 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
160 if (interfaceInfo == null) {
161 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
162 if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
163 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
164 for(MacEntry macEntry : macEntries) {
165 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
168 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName));
169 Elan elanState = ElanUtils.getElanByName(elanName);
170 List<String> elanInterfaces = elanState.getElanInterfaces();
171 elanInterfaces.remove(interfaceName);
172 if(elanInterfaces.isEmpty()) {
173 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
174 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName));
175 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
177 Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName).setKey(new ElanKey(elanName)).build();
178 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState);
182 removeElanInterface(elanInfo, interfaceInfo);
183 unbindService(elanInfo, interfaceName);
186 private void removeElanInterface(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
188 BigInteger dpId = interfaceInfo.getDpId();
189 String elanName = elanInfo.getElanInstanceName();
190 long elanTag = elanInfo.getElanTag();
191 String interfaceName = interfaceInfo.getInterfaceName();
192 Elan elanState = ElanUtils.getElanByName(elanName);
193 logger.debug("Removing the Interface:{} from elan:{}", interfaceName, elanName);
194 InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
195 Optional<ElanInterfaceMac> existingElanInterface = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
196 if(existingElanInterface.isPresent()) {
197 List<MacEntry> existingMacEntries = existingElanInterface.get().getMacEntry();
198 List<MacEntry> macEntries = new ArrayList<>();
199 if (existingMacEntries != null && !existingMacEntries.isEmpty()) {
200 macEntries.addAll(existingMacEntries);
202 if(!macEntries.isEmpty()) {
203 for (MacEntry macEntry : macEntries) {
204 logger.debug("removing the mac-entry:{} present on elanInterface:{}", macEntry.getMacAddress().getValue(), interfaceName);
205 elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(elanInfo, interfaceInfo, macEntry);
210 *This condition check is mainly to get DPN-ID in pre-provision deletion scenario after stopping CSS
212 if(dpId.equals(ElanConstants.INVALID_DPN)) {
213 ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanName);
214 if(elanDpnInterfacesList != null && !elanDpnInterfacesList.getDpnInterfaces().isEmpty()) {
215 List<DpnInterfaces> dpnIfList = elanDpnInterfacesList.getDpnInterfaces();
216 for (DpnInterfaces dpnInterface : dpnIfList) {
217 DpnInterfaces dpnIfLists = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpnInterface.getDpId());
218 if (dpnIfLists.getInterfaces().contains(interfaceName)) {
219 logger.debug("deleting the elanInterface from the ElanDpnInterface cache in pre-provision scenario of elan:{} dpn:{} interfaceName:{}", elanName, dpId, interfaceName);
220 removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName, elanTag);
226 removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName, elanTag);
229 removeStaticELanFlows(elanInfo, interfaceInfo);
230 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
231 List<String> elanInterfaces = elanState.getElanInterfaces();
232 elanInterfaces.remove(interfaceName);
234 if(elanInterfaces.isEmpty()) {
235 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
236 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnOperationDataPath(elanName));
237 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName));
238 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
239 //ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInstanceConfigurationDataPath(elanName));
241 Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName).setKey(new ElanKey(elanName)).build();
242 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState);
246 private void removeElanDpnInterfaceFromOperationalDataStore(String elanName, BigInteger dpId, String interfaceName, long elanTag) {
247 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
248 if(dpnInterfaces != null) {
249 List<String> interfaceLists = dpnInterfaces.getInterfaces();
250 interfaceLists.remove(interfaceName);
251 if (interfaceLists == null || interfaceLists.isEmpty()) {
252 deleteAllRemoteMacsInADpn(elanName, dpId, elanTag);
253 deleteElanDpnInterface(elanName, dpId);
255 updateElanDpnInterfacesList(elanName, dpId, interfaceLists);
260 private void deleteAllRemoteMacsInADpn(String elanName, BigInteger dpId, long elanTag) {
261 List<DpnInterfaces> dpnInterfaces = ElanUtils.getInvolvedDpnsInElan(elanName);
262 for (DpnInterfaces dpnInterface : dpnInterfaces) {
263 BigInteger currentDpId = dpnInterface.getDpId();
264 if (!currentDpId.equals(dpId)) {
265 for (String elanInterface : dpnInterface.getInterfaces()) {
266 ElanInterfaceMac macs = ElanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
270 for (MacEntry mac : macs.getMacEntry())
271 mdsalManager.removeFlow(dpId, MDSALUtil.buildFlow(ElanConstants.ELAN_DMAC_TABLE,
272 ElanUtils.getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, currentDpId, mac.getMacAddress().getValue(), elanTag)));
279 protected void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
280 // updating the static-Mac Entries for the existing elanInterface
281 String elanName = update.getElanInstanceName();
282 String interfaceName = update.getName();
283 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
284 List<PhysAddress> existingPhysAddress = original.getStaticMacEntries();
285 List<PhysAddress> updatedPhysAddress = update.getStaticMacEntries();
286 if(updatedPhysAddress != null && !updatedPhysAddress.isEmpty()) {
287 List<PhysAddress> existingClonedPhyAddress = new ArrayList<>();
288 if(existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
289 existingClonedPhyAddress.addAll(0, existingPhysAddress);
290 existingPhysAddress.removeAll(updatedPhysAddress);
291 updatedPhysAddress.removeAll(existingClonedPhyAddress);
292 // removing the PhyAddress which are not presented in the updated List
293 for(PhysAddress physAddress: existingPhysAddress) {
294 removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
297 // Adding the new PhysAddress which are presented in the updated List
298 if(updatedPhysAddress.size() > 0) {
299 for(PhysAddress physAddress: updatedPhysAddress) {
300 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanName, physAddress);
301 Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId);
302 if(existingMacEntry.isPresent()) {
303 elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(elanName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get());
305 elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(ElanUtils.getElanInstanceByName(elanName), interfaceName, physAddress);
309 } else if(existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
310 for( PhysAddress physAddress : existingPhysAddress) {
311 removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
317 protected void add(InstanceIdentifier<ElanInterface> identifier, ElanInterface elanInterfaceAdded) {
318 String elanInstanceName = elanInterfaceAdded.getElanInstanceName();
319 String interfaceName = elanInterfaceAdded.getName();
320 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
321 if (interfaceInfo == null) {
322 logger.warn("Interface {} is removed from Interface Oper DS due to port down ", interfaceName);
325 ElanInstance elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName);
327 if (elanInstance == null) {
328 elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setDescription(elanInterfaceAdded.getDescription()).build();
329 //Add the ElanInstance in the Configuration data-store
330 ElanUtils.UpdateOperationalDataStore(broker, idManager, elanInstance);
331 elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName);
335 Long elanTag = elanInstance.getElanTag();
336 // If elan tag is not updated, then put the elan interface into unprocessed entry map and entry. Let entries
337 // in this map get processed during ELAN update DCN.
338 if (elanTag == null) {
339 ConcurrentLinkedQueue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName);
340 if (elanInterfaces == null) {
341 elanInterfaces = new ConcurrentLinkedQueue<ElanInterface>();
343 elanInterfaces.add(elanInterfaceAdded);
344 unProcessedElanInterfaces.put(elanInstanceName, elanInterfaces);
347 addElanInterface(elanInterfaceAdded, interfaceInfo, elanInstance);
350 void handleunprocessedElanInterfaces(ElanInstance elanInstance) {
351 Queue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstance.getElanInstanceName());
352 if (elanInterfaces == null || elanInterfaces.isEmpty()) {
355 for (ElanInterface elanInterface: elanInterfaces) {
356 String interfaceName = elanInterface.getName();
357 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
358 addElanInterface(elanInterface, interfaceInfo, elanInstance);
362 void programRemoteDmacFlow(ElanInstance elanInstance, InterfaceInfo interfaceInfo){
363 ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanInstance.getElanInstanceName());
364 List<DpnInterfaces> dpnInterfaceLists = elanDpnInterfacesList.getDpnInterfaces();
365 for(DpnInterfaces dpnInterfaces : dpnInterfaceLists){
366 if(dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) {
369 List<String> remoteElanInterfaces = dpnInterfaces.getInterfaces();
370 for(String remoteIf : remoteElanInterfaces) {
371 ElanInterfaceMac elanIfMac = ElanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
372 InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf);
373 if(elanIfMac == null) {
376 List<MacEntry> remoteMacEntries = elanIfMac.getMacEntry();
377 if(remoteMacEntries != null) {
378 for (MacEntry macEntry : remoteMacEntries) {
379 PhysAddress physAddress = macEntry.getMacAddress();
380 ElanUtils.setupRemoteDmacFlow(interfaceInfo.getDpId(), remoteInterface.getDpId(),
381 remoteInterface.getInterfaceTag(),
382 elanInstance.getElanTag(),
383 physAddress.getValue(),
384 elanInstance.getElanInstanceName());
391 void addElanInterface(ElanInterface elanInterface, InterfaceInfo interfaceInfo, ElanInstance elanInstance) {
392 String interfaceName = elanInterface.getName();
393 String elanInstanceName = elanInterface.getElanInstanceName();
394 List<PhysAddress> staticMacAddresses = elanInterface.getStaticMacEntries();
395 Elan elanInfo = ElanUtils.getElanByName(elanInstanceName);
396 BigInteger dpId = null;
397 if(elanInfo == null) {
398 ElanUtils.UpdateOperationalDataStore(broker, idManager, elanInstance);
400 if(interfaceInfo != null) {
401 dpId = interfaceInfo.getDpId();
403 if(dpId != null && !dpId.equals(ElanConstants.INVALID_DPN)) {
404 InstanceIdentifier<DpnInterfaces> elanDpnInterfaces = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
405 Optional<DpnInterfaces> existingElanDpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces);
406 if (!existingElanDpnInterfaces.isPresent()) {
407 createElanInterfacesList(elanInstanceName, interfaceName, dpId);
409 * Install remote DMAC flow.
410 * This is required since this DPN is added later to the elan instance
411 * and remote DMACs of other interfaces in this elan instance are not present in the current dpn.
413 programRemoteDmacFlow(elanInstance, interfaceInfo);
415 List<String> elanInterfaces = existingElanDpnInterfaces.get().getInterfaces();
416 elanInterfaces.add(interfaceName);
417 updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces);
421 // add code to install Local/Remote BC group, unknow DMAC entry, terminating service table flow entry
422 // call bindservice of interfacemanager to create ingress table flow enty.
423 //Add interface to the ElanInterfaceForwardingEntires Container
424 createElanInterfaceTablesList(interfaceName);
425 createElanStateList(elanInstanceName, interfaceName);
426 if(interfaceInfo != null) {
427 installFlowsAndGroups(elanInstance, interfaceInfo);
429 // add the static mac addresses
430 if(staticMacAddresses != null) {
431 for (PhysAddress physAddress : staticMacAddresses) {
432 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
433 Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId);
434 if (existingMacEntry.isPresent()) {
435 elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(elanInstanceName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get());
437 elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(elanInstance, interfaceName, physAddress);
439 if(isOperational(interfaceInfo)) {
440 logger.debug("Installing Static Mac-Entry on the Elan Interface:{} with MacAddress:{}", interfaceInfo, physAddress.getValue());
441 ElanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, physAddress.getValue());
447 private Map<BigInteger, List<String>> readFePortsDbForElan(String elanName) {
448 ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanName);
449 HashMap<BigInteger, List<String>> fePortsDb = Maps.newHashMap();
450 if (elanDpnInterfacesList == null) {
453 List<DpnInterfaces> dpnInterfaces = elanDpnInterfacesList.getDpnInterfaces();
454 if (dpnInterfaces == null) {
457 for (DpnInterfaces dpnInterface : dpnInterfaces) {
458 fePortsDb.put(dpnInterface.getDpId(), dpnInterface.getInterfaces());
463 protected void removeInterfaceStaticMacEntires(String elanInstanceName, String interfaceName, PhysAddress physAddress) {
464 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
465 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
466 Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId);
468 if(!existingMacEntry.isPresent()) {
472 MacEntry macEntry = new MacEntryBuilder().setMacAddress(physAddress).setInterface(interfaceName).setKey(new MacEntryKey(physAddress)).build();
473 elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(ElanUtils.getElanInstanceByName(elanInstanceName), interfaceInfo, macEntry);
474 elanForwardingEntriesHandler.deleteElanInterfaceMacForwardingEntries(interfaceName, physAddress);
478 private InstanceIdentifier<MacEntry> getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) {
479 return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class,
480 new MacTableKey(elanName)).child(MacEntry.class, new MacEntryKey(physAddress)).build();
483 public void installFlowsAndGroups(final ElanInstance elanInfo, final InterfaceInfo interfaceInfo) {
484 if (isOperational(interfaceInfo)) {
486 // LocalBroadcast Group creation with elan-Interfaces
487 setupElanBroadcastGroups(elanInfo, interfaceInfo);
489 setupLocalBroadcastGroups(elanInfo, interfaceInfo);
490 //Terminating Service , UnknownDMAC Table.
491 setupTerminateServiceTable(elanInfo, interfaceInfo);
492 setupUnknownDMacTable(elanInfo, interfaceInfo);
493 setupFilterEqualsTable(elanInfo, interfaceInfo);
494 // bind the Elan service to the Interface
495 bindService(elanInfo, interfaceInfo.getInterfaceName());
497 //update the remote-DPNs remoteBC group entry with Tunnels
498 setElanBCGrouponOtherDpns(elanInfo, interfaceInfo);
502 public void setupFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
503 int ifTag = interfaceInfo.getInterfaceTag();
504 Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, ifTag),
505 9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
507 mdsalManager.installFlow(interfaceInfo.getDpId(), flow);
509 Flow flowEntry = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, 1000+ifTag),
510 10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag),
511 getInstructionsDrop());
513 mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntry);
516 public void removeFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
517 int ifTag = interfaceInfo.getInterfaceTag();
518 Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, ifTag),
519 9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
521 mdsalManager.removeFlow(interfaceInfo.getDpId(), flow);
523 Flow flowEntity = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, 1000+ifTag),
524 10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag),
525 getInstructionsDrop());
527 mdsalManager.removeFlow(interfaceInfo.getDpId(), flowEntity);
530 private List<Bucket> getRemoteBCGroupBucketInfos(ElanInstance elanInfo,
531 int bucketKeyStart, InterfaceInfo interfaceInfo) {
532 BigInteger dpnId = interfaceInfo.getDpId();
533 int elanTag = elanInfo.getElanTag().intValue();
534 int bucketId = bucketKeyStart;
535 List<Bucket> listBuckets = new ArrayList<Bucket>();
536 ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
537 if(elanDpns != null) {
538 List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
539 for(DpnInterfaces dpnInterface : dpnInterfaceses) {
540 if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
542 List<Action> listAction = ElanUtils.getItmEgressAction(dpnId, dpnInterface.getDpId(), (int) elanTag);
543 listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
545 } catch (Exception ex) {
546 logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() );
554 private List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo,
555 InterfaceInfo interfaceInfo, int bucketId) {
556 BigInteger dpnId = interfaceInfo.getDpId();
557 int elanTag = elanInfo.getElanTag().intValue();
558 List<Bucket> listBucketInfo = new ArrayList<Bucket>();
559 ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
560 if(elanDpns != null) {
561 List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
562 for(DpnInterfaces dpnInterface : dpnInterfaceses) {
563 if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
565 List<Action> listActionInfo = ElanUtils.getItmEgressAction(dpnId, dpnInterface.getDpId(), (int) elanTag);
566 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, 0, bucketId, 0xffffffffL, 0xffffffffL));
568 } catch (Exception ex) {
569 logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() );
574 return listBucketInfo;
577 private void setElanBCGrouponOtherDpns(ElanInstance elanInfo,
578 InterfaceInfo interfaceInfo) {
579 BigInteger dpnId = interfaceInfo.getDpId();
580 int elanTag = elanInfo.getElanTag().intValue();
581 long groupId = ElanUtils.getElanRemoteBCGID(elanTag);
582 List<Bucket> listBucket = new ArrayList<Bucket>();
584 ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
585 if(elanDpns != null) {
586 List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
587 for(DpnInterfaces dpnInterface : dpnInterfaceses) {
588 List<Bucket> remoteListBucketInfo = new ArrayList<Bucket>();
589 if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && !dpnInterface.getDpId().equals(dpnId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
590 for(String ifName : dpnInterface.getInterfaces()) {
591 // In case if there is a InterfacePort in the cache which is not in
592 // operational state, skip processing it
593 InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
594 if (!isOperational(ifInfo)) {
598 listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
601 remoteListBucketInfo.addAll(listBucket);
602 for(DpnInterfaces otherFes : dpnInterfaceses) {
603 if (ElanUtils.isDpnPresent(otherFes.getDpId()) && otherFes.getDpId() != dpnInterface.getDpId()
604 && otherFes.getInterfaces() != null && ! otherFes.getInterfaces().isEmpty()) {
606 List<Action> remoteListActionInfo = ElanUtils.getItmEgressAction(dpnInterface.getDpId(), otherFes.getDpId(), (int) elanTag);
607 remoteListBucketInfo.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,MDSALUtil.WATCH_GROUP));
609 } catch (Exception ex) {
610 logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnInterface.getDpId(), otherFes.getDpId() );
615 if(remoteListBucketInfo.size() == 0) {
616 logger.debug( "No ITM is present on Dpn - {} " ,dpnInterface.getDpId());
619 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(remoteListBucketInfo));
620 mdsalManager.syncInstallGroup(dpnInterface.getDpId(), group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
626 private void updateRemoteBCGrouponDpnTunnelEvent(ElanInstance elanInfo,
627 InterfaceInfo interfaceInfo, BigInteger dstDpId) {
628 int elanTag = elanInfo.getElanTag().intValue();
629 long groupId = ElanUtils.getElanRemoteBCGID(elanTag);
630 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), interfaceInfo.getDpId());
631 List<DpnInterfaces> elanDpns = ElanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName());
632 if(elanDpns != null) {
633 for(DpnInterfaces dpnInterface : elanDpns) {
635 List<Bucket> remoteListBucket = new ArrayList<Bucket>();
636 if(ElanUtils.isDpnPresent(dstDpId) && dpnInterface.getDpId().equals(dstDpId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
637 for(String ifName : dpnInterfaces.getInterfaces()) {
638 // In case if there is a InterfacePort in the cache which is not in
639 // operational state, skip processing it
640 InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
641 if (!isOperational(ifInfo)) {
645 remoteListBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
649 List<Action> remoteListActionInfo = ElanUtils.getItmEgressAction(interfaceInfo.getDpId(), dstDpId, (int) elanTag);
650 remoteListBucket.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
652 } catch (Exception ex) {
653 logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnInterface.getDpId(), dstDpId);
656 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(remoteListBucket));
657 mdsalManager.syncInstallGroup(interfaceInfo.getDpId(), group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
666 * Returns the bucket info with the given interface as the only bucket.
668 private Bucket getLocalBCGroupBucketInfo(InterfaceInfo interfaceInfo, int bucketIdStart) {
669 return MDSALUtil.buildBucket(getInterfacePortActions(interfaceInfo), MDSALUtil.GROUP_WEIGHT, bucketIdStart, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP);
672 private List<MatchInfo> getMatchesForElanTag(Long elanTag) {
673 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
675 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
676 ElanUtils.getElanMetadataLabel(elanTag),
677 MetaDataUtil.METADATA_MASK_SERVICE }));
681 private List<Instruction> getInstructionsForOutGroup(
683 List<Instruction> mkInstructions = new ArrayList<Instruction>();
684 List <Action> actions = new ArrayList <Action> ();
685 actions.add(new ActionInfo(ActionType.group, new String[]{Long.toString(groupId)}).buildAction());
686 mkInstructions.add(ElanUtils.getWriteActionInstruction(actions));
687 return mkInstructions;
690 public void removeFlowsAndGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
691 removeStaticELanFlows(elanInfo, interfaceInfo);
692 unbindService(elanInfo, interfaceInfo.getInterfaceName());
695 public void installMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
696 String interfaceName = interfaceInfo.getInterfaceName();
697 BigInteger currentDpn = interfaceInfo.getDpId();
698 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
699 if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
700 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
701 for(MacEntry macEntry : macEntries) {
702 PhysAddress physAddress = macEntry.getMacAddress();
703 ElanUtils.setupMacFlows(elanInfo, interfaceInfo, macEntry.isIsStaticAddress() ? ElanConstants.STATIC_MAC_TIMEOUT : elanInfo.getMacTimeout(), physAddress.getValue());
705 //Programming the remoteDMACFlows
706 ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
707 List<DpnInterfaces> dpnInterfaceLists = elanDpnInterfacesList.getDpnInterfaces();
708 for(DpnInterfaces dpnInterfaces : dpnInterfaceLists){
709 if(dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) {
712 List<String> remoteElanInterfaces = dpnInterfaces.getInterfaces();
713 for(String remoteIf : remoteElanInterfaces) {
714 ElanInterfaceMac elanIfMac = ElanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
715 InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf);
716 if(elanIfMac == null) {
719 List<MacEntry> remoteMacEntries = elanIfMac.getMacEntry();
720 if(remoteMacEntries != null) {
721 for (MacEntry macEntry : remoteMacEntries) {
722 PhysAddress physAddress = macEntry.getMacAddress();
723 ElanUtils.setupRemoteDmacFlow(currentDpn, remoteInterface.getDpId(), remoteInterface.getInterfaceTag(), elanInfo.getElanTag(), physAddress.getValue(), elanInfo.getElanInstanceName());
731 // Install DMAC entry on dst DPN
732 public void installDMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId) {
733 String interfaceName = interfaceInfo.getInterfaceName();
734 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
735 if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
736 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
737 for(MacEntry macEntry : macEntries) {
738 PhysAddress physAddress = macEntry.getMacAddress();
739 ElanUtils.setupDMacFlowonRemoteDpn(elanInfo, interfaceInfo, dstDpId, physAddress.getValue());
744 public void removeMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
745 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceInfo.getInterfaceName());
746 if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
747 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
748 for(MacEntry macEntry : macEntries) {
749 ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry);
754 public void setupElanBroadcastGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
755 List<Bucket> listBucket = new ArrayList<Bucket>();
757 BigInteger dpnId = interfaceInfo.getDpId();
758 long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag());
760 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpnId);
761 for(String ifName : dpnInterfaces.getInterfaces()) {
762 // In case if there is a InterfacePort in the cache which is not in
763 // operational state, skip processing it
764 InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
765 if (!isOperational(ifInfo)) {
769 listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
772 List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, interfaceInfo, bucketId);
773 listBucket.addAll(listBucketInfoRemote);
775 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket));
776 logger.trace("installing the localBroadCast Group:{}", group);
777 // In the case of OVS disconnected we receive null object when we query Interface Operation datastore
778 // so the size of the bucket will be zero
779 if(listBucket.size() == 0) {
780 mdsalManager.syncRemoveGroup(dpnId, group);
782 mdsalManager.syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
786 public void setupLocalBroadcastGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
787 List<Bucket> listBucket = new ArrayList<Bucket>();
789 BigInteger dpnId = interfaceInfo.getDpId();
790 long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
792 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpnId);
793 for(String ifName : dpnInterfaces.getInterfaces()) {
794 // In case if there is a InterfacePort in the cache which is not in
795 // operational state, skip processing it
796 InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
797 if (!isOperational(ifInfo)) {
801 listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
806 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket));
807 logger.trace("installing the localBroadCast Group:{}", group);
808 // In the case of OVS disconnected we receive null object for the Interface Operation datastore
809 // so the size of the bucket will be zero
810 if(listBucket.size() == 0) {
811 mdsalManager.syncRemoveGroup(dpnId, group);
813 mdsalManager.syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
817 public void removeLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
818 BigInteger dpnId = interfaceInfo.getDpId();
819 long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
820 List<Bucket> listBuckets = new ArrayList<>();
822 listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
823 //listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, 1, interfaceInfo));
824 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets));
825 logger.trace("deleted the localBroadCast Group:{}", group);
826 mdsalManager.syncRemoveGroup(dpnId, group);
829 public void removeElanBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
831 List<Bucket> listBuckets = new ArrayList<>();
832 listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
834 listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo));
835 BigInteger dpnId = interfaceInfo.getDpId();
836 long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag());
837 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets));
838 logger.trace("deleting the remoteBroadCast group:{}", group);
839 mdsalManager.syncRemoveGroup(dpnId, group);
842 public void setupTerminateServiceTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
843 long elanTag = elanInfo.getElanTag();
844 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE, getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, elanTag),
845 5, String.format("%s:%d","ITM Flow Entry ",elanTag), 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)), ElanUtils.getTunnelMatchesForServiceId((int)elanTag),
846 getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
848 mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity);
851 public void setupUnknownDMacTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
852 long elanTag = elanInfo.getElanTag();
853 Flow flowEntity = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag),
854 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag),
855 getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGID(elanTag)));
857 mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity);
860 private void removeStaticELanFlows(final ElanInstance elanInfo, final InterfaceInfo interfaceInfo) {
861 BigInteger dpId = interfaceInfo.getDpId();
863 * If there are not elan ports, remove the unknown smac and default dmac
866 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpId);
867 if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null || dpnInterfaces.getInterfaces().isEmpty()) {
868 // No more Elan Interfaces in this DPN
869 logger.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId);
870 removeDefaultTermFlow(dpId, elanInfo.getElanTag());
871 removeUnknownDmacFlow(dpId, elanInfo);
872 removeElanBroadcastGroup(elanInfo, interfaceInfo);
873 removeLocalBroadcastGroup(elanInfo, interfaceInfo);
874 removeFilterEqualsTable(elanInfo, interfaceInfo);
876 setupElanBroadcastGroups(elanInfo, interfaceInfo);
877 setupLocalBroadcastGroups(elanInfo, interfaceInfo);
878 removeFilterEqualsTable(elanInfo, interfaceInfo);
882 private void removeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo) {
883 Flow flow = getUnknownDmacFlowEntity(dpId, elanInfo);
884 mdsalManager.removeFlow(dpId, flow);
887 private void removeDefaultTermFlow(BigInteger dpId, long elanTag) {
888 ElanUtils.removeTerminatingServiceAction(dpId, (int) elanTag);
891 private void bindService(ElanInstance elanInfo, String interfaceName) {
892 // interfaceManager.bindService(interfaceName, ElanUtils.getServiceInfo(elanInfo.getElanInstanceName(), elanInfo.getElanTag(), interfaceName));
894 int priority = ElanConstants.ELAN_SERVICE_PRIORITY;
895 int instructionKey = 0;
896 List<Instruction> instructions = new ArrayList<Instruction>();
897 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(ElanUtils.getElanMetadataLabel(elanInfo.getElanTag()), MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey));
898 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(ElanConstants.ELAN_SMAC_TABLE, ++instructionKey));
901 ElanUtils.getBoundServices(String.format("%s.%s.%s", "vpn",elanInfo.getElanInstanceName(), interfaceName),
902 ElanConstants.ELAN_SERVICE_INDEX, priority,
903 ElanConstants.COOKIE_ELAN_INGRESS_TABLE, instructions);
904 ElanUtils.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
905 ElanUtils.buildServiceId(interfaceName, ElanConstants.ELAN_SERVICE_INDEX), serviceInfo);
908 private void unbindService(ElanInstance elanInfo, String interfaceName) {
909 ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
910 ElanUtils.buildServiceId(interfaceName,ElanConstants.ELAN_SERVICE_INDEX),
911 ElanUtils.DEFAULT_CALLBACK);
914 private void unbindService(ElanInstance elanInfo, String interfaceName, int vlanId) {
915 ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
916 ElanUtils.buildServiceId(interfaceName,ElanConstants.ELAN_SERVICE_INDEX),
917 ElanUtils.DEFAULT_CALLBACK);
920 private Flow getUnknownDmacFlowEntity(BigInteger dpId, ElanInstance elanInfo) {
921 long elanTag = elanInfo.getElanTag();
922 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
924 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
925 ElanUtils.getElanMetadataLabel(elanTag),
926 MetaDataUtil.METADATA_MASK_SERVICE }));
928 List<Instruction> mkInstructions = new ArrayList<Instruction>();
929 List <Action> actionsInfos = new ArrayList <Action> ();
930 actionsInfos.add(new ActionInfo(ActionType.group, new String[]{Long.toString(ElanUtils.getElanRemoteBCGID(elanTag))}, 0).buildAction());
931 mkInstructions.add(ElanUtils.getWriteActionInstruction(actionsInfos));
933 Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag),
934 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)),
935 mkMatches, mkInstructions);
939 private String getFlowRef(long tableId, long elanTag) {
940 return new StringBuffer().append(tableId).append(elanTag).toString();
943 private List<Action> getInterfacePortActions(InterfaceInfo interfaceInfo) {
944 List<Action> listAction = new ArrayList<Action>();
946 listAction.add((new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {BigInteger.valueOf(interfaceInfo.getInterfaceTag())}, actionKey)).buildAction());
948 listAction.add((new ActionInfo(ActionType.nx_resubmit, new String[] {Short.toString((short)55)}, actionKey)).buildAction());
952 private void updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId, List<String> interfaceNames) {
953 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
954 .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
955 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
960 * Delete elan dpn interface from operational DS.
962 * @param elanInstanceName
963 * the elan instance name
967 private void deleteElanDpnInterface(String elanInstanceName, BigInteger dpId) {
968 MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL,
969 ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId));
972 private List<String> createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId) {
973 List<String> interfaceNames = new ArrayList<String>();
974 interfaceNames.add(interfaceName);
975 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
976 .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
977 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
979 return interfaceNames;
982 private void createElanInterfaceTablesList(String interfaceName) {
983 InstanceIdentifier<ElanInterfaceMac> elanInterfaceMacTables = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
984 Optional<ElanInterfaceMac> interfaceMacTables = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceMacTables);
985 // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries..
986 if(!interfaceMacTables.isPresent()) {
987 ElanInterfaceMac elanInterfaceMacTable = new ElanInterfaceMacBuilder().setElanInterface(interfaceName).setKey(new ElanInterfaceMacKey(interfaceName)).build();
988 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName),
989 elanInterfaceMacTable);
993 private void createElanStateList(String elanInstanceName, String interfaceName) {
994 InstanceIdentifier<Elan> elanInstance = ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName);
995 Optional<Elan> elanInterfaceLists = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInstance);
996 // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries..
997 if(elanInterfaceLists.isPresent()) {
998 List<String> interfaceLists = elanInterfaceLists.get().getElanInterfaces();
999 if(interfaceLists == null) {
1000 interfaceLists = new ArrayList<>();
1002 interfaceLists.add(interfaceName);
1003 Elan elanState = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(interfaceLists).setKey(new ElanKey(elanInstanceName)).build();
1004 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName), elanState);
1008 private boolean isOperational(InterfaceInfo interfaceInfo) {
1009 if (interfaceInfo == null) {
1012 return ((interfaceInfo.getOpState() == InterfaceInfo.InterfaceOpState.UP) && (interfaceInfo.getAdminState() == InterfaceInfo.InterfaceAdminState.ENABLED));
1015 protected void updatedIfPrimaryAttributeChanged(ElanInterface elanInterface, boolean isUpdated) {
1016 String interfaceName = elanInterface.getName();
1017 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
1018 BigInteger dpId = interfaceInfo.getDpId();
1019 InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
1020 Optional<ElanInterfaceMac> existingElanInterface = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
1021 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanInterface.getElanInstanceName());
1023 if(!existingElanInterface.isPresent()) {
1027 List<MacEntry> macEntries = existingElanInterface.get().getMacEntry();
1028 if(macEntries != null && !macEntries.isEmpty()) {
1029 for (MacEntry macEntry : macEntries) {
1031 ElanUtils.setupMacFlows(elanInfo, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, macEntry.getMacAddress().getValue());
1033 ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry);
1038 InstanceIdentifier<DpnInterfaces> dpnInterfaceId = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInterface.getElanInstanceName(), interfaceInfo.getDpId());
1039 Optional<DpnInterfaces> dpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, dpnInterfaceId);
1040 List<String> interfaceLists = dpnInterfaces.get().getInterfaces();
1043 interfaceLists.add(elanInterface.getName());
1045 interfaceLists.remove(elanInterface.getName());
1048 DpnInterfaces updateDpnInterfaces = new DpnInterfacesBuilder().setInterfaces(interfaceLists).setDpId(dpId).setKey(new DpnInterfacesKey(dpId)).build();
1049 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, dpnInterfaceId, updateDpnInterfaces);
1052 installFlowsAndGroups(elanInfo, interfaceInfo);
1054 removeStaticELanFlows(elanInfo, interfaceInfo);
1055 unbindService(elanInfo, interfaceName);
1059 public void handleTunnelStateEvent(BigInteger srcDpId, BigInteger dstDpId) {
1060 ElanDpnInterfaces dpnInterfaceLists = ElanUtils.getElanDpnInterfacesList();
1061 Set<String> elanInstancesMap = new HashSet<>();
1062 if(dpnInterfaceLists == null) {
1065 List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
1066 for(ElanDpnInterfacesList elanDpns: elanDpnIf) {
1068 String elanName = elanDpns.getElanInstanceName();
1069 List<DpnInterfaces> dpnInterfaces = elanDpns.getDpnInterfaces();
1070 if(dpnInterfaces == null) {
1073 for (DpnInterfaces dpnIf : dpnInterfaces) {
1074 if(dpnIf.getDpId().equals(srcDpId) || dpnIf.getDpId().equals(dstDpId)) {
1079 logger.debug("Elan instance:{} is present b/w srcDpn:{} and dstDpn:{}", elanName, srcDpId, dstDpId);
1080 DpnInterfaces dpnInterface = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, srcDpId);
1081 Set<String> interfaceLists = new HashSet<>();
1082 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanName);
1083 interfaceLists.addAll(dpnInterface.getInterfaces());
1084 for(String ifName : interfaceLists) {
1085 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(ifName);
1086 if (isOperational(interfaceInfo)) {
1087 if (interfaceInfo.getDpId().equals(srcDpId) && !elanInstancesMap.contains(elanDpns.getElanInstanceName())) {
1088 elanInstancesMap.add(elanDpns.getElanInstanceName());
1089 elanInterfaceManager.updateRemoteBCGrouponDpnTunnelEvent(elanInfo, interfaceInfo, dstDpId);
1091 elanInterfaceManager.installDMacAddressTables(elanInfo, interfaceInfo, dstDpId);
1099 public void handleInterfaceUpated(InterfaceInfo interfaceInfo, ElanInstance elanInstance, boolean isStateUp) {
1100 BigInteger dpId = interfaceInfo.getDpId();
1101 String elanName = elanInstance.getElanInstanceName();
1102 String ifName = interfaceInfo.getInterfaceName();
1103 logger.trace("Handling interface update event for interface with info {} , state {}", interfaceInfo, isStateUp);
1106 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
1107 if(dpnInterfaces == null) {
1108 createElanInterfacesList(elanName, interfaceInfo.getInterfaceName(), dpId);
1110 List<String> dpnElanInterfaces = dpnInterfaces.getInterfaces();
1111 dpnElanInterfaces.add(interfaceInfo.getInterfaceName());
1112 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
1113 .setInterfaces(dpnElanInterfaces).setKey(new DpnInterfacesKey(dpId)).build();
1114 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanName, interfaceInfo.getDpId()), dpnInterface);
1117 logger.trace("ElanInterface Service is installed for interface:{}", ifName);
1118 elanInterfaceManager.installFlowsAndGroups(elanInstance, interfaceInfo);
1119 elanInterfaceManager.installMacAddressTables(elanInstance, interfaceInfo);
1122 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
1123 if(dpnInterfaces != null) {
1124 List<String> dpnElanInterfaces = dpnInterfaces.getInterfaces();
1125 dpnElanInterfaces.remove(interfaceInfo.getInterfaceName());
1126 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
1127 .setInterfaces(dpnElanInterfaces).setKey(new DpnInterfacesKey(dpId)).build();
1128 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanName, interfaceInfo.getDpId()), dpnInterface);
1130 logger.trace("ElanInterface Service is removed for the interface:{}", ifName);
1131 elanInterfaceManager.removeMacAddressTables(elanInstance, interfaceInfo);
1132 elanInterfaceManager.removeFlowsAndGroups(elanInstance, interfaceInfo);
1136 private List<MatchInfo> getMatchesForFilterEqualsLPortTag(int LportTag) {
1137 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1138 // Matching metadata
1139 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
1140 MetaDataUtil.getLportTagMetaData(LportTag),
1141 MetaDataUtil.METADATA_MASK_LPORT_TAG }));
1142 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(LportTag)}));
1147 private List<MatchInfo> getTunnelIdMatchForFilterEqualsLPortTag(int LportTag) {
1148 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1149 // Matching metadata
1150 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
1151 BigInteger.valueOf(LportTag)}));
1157 private List<Instruction> getInstructionsDrop() {
1158 List<Instruction> mkInstructions = new ArrayList<Instruction>();
1159 List <Action> actionsInfos = new ArrayList <Action> ();
1160 actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[]{}).buildAction());
1161 mkInstructions.add(ElanUtils.getWriteActionInstruction(actionsInfos));
1162 return mkInstructions;