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 java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.HashSet;
13 import java.util.List;
15 import java.util.Queue;
17 import java.util.concurrent.ConcurrentHashMap;
18 import java.util.concurrent.ConcurrentLinkedQueue;
19 import java.util.concurrent.ConcurrentMap;
21 import org.apache.commons.lang3.StringUtils;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
24 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.elanmanager.utils.ElanL2GwCacheUtils;
27 import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
28 import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayUtils;
29 import org.opendaylight.vpnservice.elan.utils.ElanConstants;
30 import org.opendaylight.vpnservice.elan.utils.ElanUtils;
31 import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
32 import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo.InterfaceType;
33 import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
34 import org.opendaylight.vpnservice.itm.globals.ITMConstants;
35 import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
36 import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
37 import org.opendaylight.vpnservice.mdsalutil.ActionType;
38 import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
39 import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
40 import org.opendaylight.vpnservice.mdsalutil.InstructionType;
41 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
42 import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
43 import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
44 import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
45 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
46 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
47 import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
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.action.types.rev131112.action.list.Action;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanDpnInterfaces;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanForwardingTables;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInterfaces;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesKey;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.forwarding.tables.MacTable;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.forwarding.tables.MacTableKey;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.Elan;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.ElanBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.ElanKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntry;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
83 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
84 import org.opendaylight.yangtools.concepts.ListenerRegistration;
85 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
86 import org.slf4j.Logger;
87 import org.slf4j.LoggerFactory;
89 import com.google.common.base.Optional;
90 import com.google.common.base.Preconditions;
93 * Class in charge of handling creations, modifications and removals of ElanInterfaces.
95 * @see org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface
98 public class ElanInterfaceManager extends AbstractDataChangeListener<ElanInterface> implements AutoCloseable {
100 private static ElanInterfaceManager elanInterfaceManager = new ElanInterfaceManager();
101 private ListenerRegistration<DataChangeListener> elanInterfaceListenerRegistration;
102 private ListenerRegistration<DataChangeListener> itmInterfaceListenerRegistration;
103 private OdlInterfaceRpcService interfaceManagerRpcService;
104 private DataBroker broker;
105 private IMdsalApiManager mdsalManager;
106 private IInterfaceManager interfaceManager;
107 private IdManagerService idManager;
109 private ElanForwardingEntriesHandler elanForwardingEntriesHandler;
110 private Map<String, ConcurrentLinkedQueue<ElanInterface>> unProcessedElanInterfaces =
111 new ConcurrentHashMap<String, ConcurrentLinkedQueue<ElanInterface>> ();
113 private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceManager.class);
115 public ElanInterfaceManager() {
116 super(ElanInterface.class);
119 public static ElanInterfaceManager getElanInterfaceManager() {
120 return elanInterfaceManager;
123 public void setMdSalApiManager(IMdsalApiManager mdsalManager) {
124 this.mdsalManager = mdsalManager;
127 public void setInterfaceManagerRpcService(OdlInterfaceRpcService ifManager) {
128 this.interfaceManagerRpcService = ifManager;
131 public void setElanForwardingEntriesHandler(ElanForwardingEntriesHandler elanForwardingEntriesHandler) {
132 this.elanForwardingEntriesHandler = elanForwardingEntriesHandler;
135 public void setInterfaceManager(IInterfaceManager interfaceManager) {
136 this.interfaceManager = interfaceManager;
139 public void setDataBroker(DataBroker broker) {
140 this.broker = broker;
144 public void close() throws Exception {
145 if (elanInterfaceListenerRegistration != null) {
147 elanInterfaceListenerRegistration.close();
148 } catch (final Exception e) {
149 logger.error("Error when cleaning up DataChangeListener.", e);
151 elanInterfaceListenerRegistration = null;
155 public void registerListener() {
157 elanInterfaceListenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
158 getElanInterfaceWildcardPath(), ElanInterfaceManager.this, DataChangeScope.SUBTREE);
159 } catch (final Exception e) {
160 logger.error("ELAN Interface DataChange listener registration failed !", e);
161 throw new IllegalStateException("ELAN Interface registration Listener failed.", e);
165 private InstanceIdentifier<?> getElanInterfaceWildcardPath() {
166 return InstanceIdentifier.create(ElanInterfaces.class).child(ElanInterface.class);
169 public void setIdManager(IdManagerService idManager) {
170 this.idManager = idManager;
174 protected void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
175 String interfaceName = del.getName();
176 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(del.getElanInstanceName());
177 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
178 String elanInstanceName = elanInfo.getElanInstanceName();
179 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
180 ElanInterfaceRemoveWorker configWorker = new ElanInterfaceRemoveWorker(elanInstanceName, elanInfo, interfaceName, interfaceInfo, this);
181 coordinator.enqueueJob(elanInstanceName, configWorker, ElanConstants.JOB_MAX_RETRIES);
184 public void removeElanInterface(ElanInstance elanInfo, String interfaceName, InterfaceInfo interfaceInfo) {
185 String elanName = elanInfo.getElanInstanceName();
186 if (interfaceInfo == null) {
187 // Interface does not exist in ConfigDS, so lets remove everything about that interface related to Elan
188 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
189 if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
190 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
191 for(MacEntry macEntry : macEntries) {
192 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()));
195 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName));
196 Elan elanState = ElanUtils.getElanByName(elanName);
197 List<String> elanInterfaces = elanState.getElanInterfaces();
198 elanInterfaces.remove(interfaceName);
199 if(elanInterfaces.isEmpty()) {
200 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
201 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName));
202 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
204 Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName).setKey(new ElanKey(elanName)).build();
205 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState);
208 removeElanInterface(elanInfo, interfaceInfo);
209 unbindService(elanInfo, interfaceName);
213 private void removeElanInterface(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
215 BigInteger dpId = interfaceInfo.getDpId();
216 String elanName = elanInfo.getElanInstanceName();
217 long elanTag = elanInfo.getElanTag();
218 String interfaceName = interfaceInfo.getInterfaceName();
219 Elan elanState = ElanUtils.getElanByName(elanName);
220 logger.debug("Removing the Interface:{} from elan:{}", interfaceName, elanName);
221 InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
222 Optional<ElanInterfaceMac> existingElanInterface = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
223 if(existingElanInterface.isPresent()) {
224 List<PhysAddress> macAddresses = new ArrayList<PhysAddress>();
225 List<MacEntry> existingMacEntries = existingElanInterface.get().getMacEntry();
226 List<MacEntry> macEntries = new ArrayList<>();
227 if (existingMacEntries != null && !existingMacEntries.isEmpty()) {
228 macEntries.addAll(existingMacEntries);
230 if(!macEntries.isEmpty()) {
231 for (MacEntry macEntry : macEntries) {
232 logger.debug("removing the mac-entry:{} present on elanInterface:{}", macEntry.getMacAddress().getValue(), interfaceName);
233 elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(elanInfo, interfaceInfo, macEntry);
234 macAddresses.add(macEntry.getMacAddress());
237 // Removing all those MACs from External Devices belonging to this ELAN
238 if ( elanInfo.getVni() != null && elanInfo.getVni() != 0 ) {
239 ElanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInfo, macAddresses);
244 *This condition check is mainly to get DPN-ID in pre-provision deletion scenario after stopping CSS
246 if(dpId.equals(ElanConstants.INVALID_DPN)) {
247 ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanName);
248 if(elanDpnInterfacesList != null && !elanDpnInterfacesList.getDpnInterfaces().isEmpty()) {
249 List<DpnInterfaces> dpnIfList = elanDpnInterfacesList.getDpnInterfaces();
250 for (DpnInterfaces dpnInterface : dpnIfList) {
251 DpnInterfaces dpnIfLists = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpnInterface.getDpId());
252 if (dpnIfLists.getInterfaces().contains(interfaceName)) {
253 logger.debug("deleting the elanInterface from the ElanDpnInterface cache in pre-provision scenario of elan:{} dpn:{} interfaceName:{}", elanName, dpId, interfaceName);
254 removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName, elanTag);
260 removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName, elanTag);
263 removeStaticELanFlows(elanInfo, interfaceInfo);
264 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
265 List<String> elanInterfaces = elanState.getElanInterfaces();
266 elanInterfaces.remove(interfaceName);
268 if(elanInterfaces.isEmpty()) {
269 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName));
270 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnOperationDataPath(elanName));
271 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName));
272 ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
273 //ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInstanceConfigurationDataPath(elanName));
275 Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName).setKey(new ElanKey(elanName)).build();
276 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState);
280 private void removeElanDpnInterfaceFromOperationalDataStore(String elanName, BigInteger dpId, String interfaceName, long elanTag) {
281 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
282 if(dpnInterfaces != null) {
283 List<String> interfaceLists = dpnInterfaces.getInterfaces();
284 interfaceLists.remove(interfaceName);
286 if (interfaceLists == null || interfaceLists.isEmpty()) {
287 deleteAllRemoteMacsInADpn(elanName, dpId, elanTag);
288 deleteElanDpnInterface(elanName, dpId);
290 updateElanDpnInterfacesList(elanName, dpId, interfaceLists);
295 private void deleteAllRemoteMacsInADpn(String elanName, BigInteger dpId, long elanTag) {
296 List<DpnInterfaces> dpnInterfaces = ElanUtils.getInvolvedDpnsInElan(elanName);
297 for (DpnInterfaces dpnInterface : dpnInterfaces) {
298 BigInteger currentDpId = dpnInterface.getDpId();
299 if (!currentDpId.equals(dpId)) {
300 for (String elanInterface : dpnInterface.getInterfaces()) {
301 ElanInterfaceMac macs = ElanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
305 for (MacEntry mac : macs.getMacEntry())
306 mdsalManager.removeFlow(dpId, MDSALUtil.buildFlow(ElanConstants.ELAN_DMAC_TABLE,
307 ElanUtils.getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, currentDpId, mac.getMacAddress().getValue(), elanTag)));
314 protected void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
315 // updating the static-Mac Entries for the existing elanInterface
316 String elanName = update.getElanInstanceName();
317 String interfaceName = update.getName();
318 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
319 List<PhysAddress> existingPhysAddress = original.getStaticMacEntries();
320 List<PhysAddress> updatedPhysAddress = update.getStaticMacEntries();
321 if(updatedPhysAddress != null && !updatedPhysAddress.isEmpty()) {
322 List<PhysAddress> existingClonedPhyAddress = new ArrayList<>();
323 if(existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
324 existingClonedPhyAddress.addAll(0, existingPhysAddress);
325 existingPhysAddress.removeAll(updatedPhysAddress);
326 updatedPhysAddress.removeAll(existingClonedPhyAddress);
327 // removing the PhyAddress which are not presented in the updated List
328 for(PhysAddress physAddress: existingPhysAddress) {
329 removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
332 // Adding the new PhysAddress which are presented in the updated List
333 if(updatedPhysAddress.size() > 0) {
334 for(PhysAddress physAddress: updatedPhysAddress) {
335 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanName, physAddress);
336 Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId);
337 if(existingMacEntry.isPresent()) {
338 elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(elanName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get());
340 elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(ElanUtils.getElanInstanceByName(elanName), interfaceName, physAddress);
344 } else if(existingPhysAddress != null && !existingPhysAddress.isEmpty()) {
345 for( PhysAddress physAddress : existingPhysAddress) {
346 removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress);
352 protected void add(InstanceIdentifier<ElanInterface> identifier, ElanInterface elanInterfaceAdded) {
353 String elanInstanceName = elanInterfaceAdded.getElanInstanceName();
354 String interfaceName = elanInterfaceAdded.getName();
355 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
356 if (interfaceInfo == null) {
357 logger.warn("Interface {} is removed from Interface Oper DS due to port down ", interfaceName);
360 ElanInstance elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName);
362 if (elanInstance == null) {
363 elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setDescription(elanInterfaceAdded.getDescription()).build();
364 //Add the ElanInstance in the Configuration data-store
365 ElanUtils.updateOperationalDataStore(broker, idManager, elanInstance);
366 elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName);
370 Long elanTag = elanInstance.getElanTag();
371 // If elan tag is not updated, then put the elan interface into unprocessed entry map and entry. Let entries
372 // in this map get processed during ELAN update DCN.
373 if (elanTag == null) {
374 ConcurrentLinkedQueue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName);
375 if (elanInterfaces == null) {
376 elanInterfaces = new ConcurrentLinkedQueue<ElanInterface>();
378 elanInterfaces.add(elanInterfaceAdded);
379 unProcessedElanInterfaces.put(elanInstanceName, elanInterfaces);
382 DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
383 ElanInterfaceAddWorker addWorker = new ElanInterfaceAddWorker(elanInstanceName, elanInterfaceAdded,
384 interfaceInfo, elanInstance, this);
385 coordinator.enqueueJob(elanInstanceName, addWorker, ElanConstants.JOB_MAX_RETRIES);
388 void handleunprocessedElanInterfaces(ElanInstance elanInstance) {
389 Queue<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstance.getElanInstanceName());
390 if (elanInterfaces == null || elanInterfaces.isEmpty()) {
393 for (ElanInterface elanInterface: elanInterfaces) {
394 String interfaceName = elanInterface.getName();
395 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
396 addElanInterface(elanInterface, interfaceInfo, elanInstance);
400 void programRemoteDmacFlow(ElanInstance elanInstance, InterfaceInfo interfaceInfo){
401 ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanInstance.getElanInstanceName());
402 List<DpnInterfaces> dpnInterfaceLists = elanDpnInterfacesList.getDpnInterfaces();
403 for(DpnInterfaces dpnInterfaces : dpnInterfaceLists){
404 if(dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) {
407 List<String> remoteElanInterfaces = dpnInterfaces.getInterfaces();
408 for(String remoteIf : remoteElanInterfaces) {
409 ElanInterfaceMac elanIfMac = ElanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
410 InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf);
411 if(elanIfMac == null) {
414 List<MacEntry> remoteMacEntries = elanIfMac.getMacEntry();
415 if(remoteMacEntries != null) {
416 for (MacEntry macEntry : remoteMacEntries) {
417 PhysAddress physAddress = macEntry.getMacAddress();
418 ElanUtils.setupRemoteDmacFlow(interfaceInfo.getDpId(), remoteInterface.getDpId(),
419 remoteInterface.getInterfaceTag(),
420 elanInstance.getElanTag(),
421 physAddress.getValue(),
422 elanInstance.getElanInstanceName());
429 void addElanInterface(ElanInterface elanInterface, InterfaceInfo interfaceInfo, ElanInstance elanInstance) {
430 Preconditions.checkNotNull(elanInstance, "elanInstance cannot be null");
431 Preconditions.checkNotNull(interfaceInfo, "interfaceInfo cannot be null");
432 Preconditions.checkNotNull(elanInterface, "elanInterface cannot be null");
434 String interfaceName = elanInterface.getName();
435 String elanInstanceName = elanInterface.getElanInstanceName();
436 List<PhysAddress> staticMacAddresses = elanInterface.getStaticMacEntries();
438 Elan elanInfo = ElanUtils.getElanByName(elanInstanceName);
439 if(elanInfo == null) {
440 ElanUtils.updateOperationalDataStore(broker, idManager, elanInstance);
443 // Specific actions to the DPN where the ElanInterface has been added, for example, programming the
444 // External tunnel table if needed or adding the ElanInterface to the DpnInterfaces in the operational DS.
445 BigInteger dpId = ( interfaceInfo != null ) ? dpId = interfaceInfo.getDpId() : null;
446 if(dpId != null && !dpId.equals(ElanConstants.INVALID_DPN)) {
447 InstanceIdentifier<DpnInterfaces> elanDpnInterfaces = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
448 Optional<DpnInterfaces> existingElanDpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces);
449 if (!existingElanDpnInterfaces.isPresent()) {
450 // ELAN's 1st ElanInterface added to this DPN
451 createElanInterfacesList(elanInstanceName, interfaceName, dpId);
453 * Install remote DMAC flow.
454 * This is required since this DPN is added later to the elan instance
455 * and remote DMACs of other interfaces in this elan instance are not present in the current dpn.
457 programRemoteDmacFlow(elanInstance, interfaceInfo);
458 // The 1st ElanInterface in a DPN must program the Ext Tunnel table, but only if Elan has VNI
459 if ( elanInstance.getVni() != null && elanInstance.getVni().longValue() != 0 ) {
460 setExternalTunnelTable(dpId, elanInstance);
462 ElanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance);
464 List<String> elanInterfaces = existingElanDpnInterfaces.get().getInterfaces();
465 elanInterfaces.add(interfaceName);
466 if (elanInterfaces.size() == 1) {//1st dpn interface
467 ElanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance);
469 updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces);
473 // add code to install Local/Remote BC group, unknow DMAC entry, terminating service table flow entry
474 // call bindservice of interfacemanager to create ingress table flow enty.
475 //Add interface to the ElanInterfaceForwardingEntires Container
476 createElanInterfaceTablesList(interfaceName);
477 createElanStateList(elanInstanceName, interfaceName);
478 if (interfaceInfo != null) {
479 installFlowsAndGroups(elanInstance, interfaceInfo);
481 // add the static mac addresses
482 if (staticMacAddresses != null) {
483 boolean isInterfaceOperational = isOperational(interfaceInfo);
484 for (PhysAddress physAddress : staticMacAddresses) {
485 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
486 Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId);
487 if (existingMacEntry.isPresent()) {
488 elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(elanInstanceName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get());
490 elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(elanInstance, interfaceName, physAddress);
493 if ( isInterfaceOperational ) {
494 // Setting SMAC, DMAC, UDMAC in this DPN and also in other DPNs
495 ElanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, physAddress.getValue());
499 if( isInterfaceOperational ) {
500 // Add MAC in TOR's remote MACs via OVSDB. Outside of the loop on purpose.
501 ElanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(), dpId, staticMacAddresses);
506 protected void removeInterfaceStaticMacEntires(String elanInstanceName, String interfaceName, PhysAddress physAddress) {
507 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
508 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
509 Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId);
511 if(!existingMacEntry.isPresent()) {
515 MacEntry macEntry = new MacEntryBuilder().setMacAddress(physAddress).setInterface(interfaceName).setKey(new MacEntryKey(physAddress)).build();
516 elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(ElanUtils.getElanInstanceByName(elanInstanceName), interfaceInfo, macEntry);
517 elanForwardingEntriesHandler.deleteElanInterfaceMacForwardingEntries(interfaceName, physAddress);
521 private InstanceIdentifier<MacEntry> getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) {
522 return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class,
523 new MacTableKey(elanName)).child(MacEntry.class, new MacEntryKey(physAddress)).build();
526 public void installFlowsAndGroups(final ElanInstance elanInfo, final InterfaceInfo interfaceInfo) {
527 if (isOperational(interfaceInfo)) {
529 // LocalBroadcast Group creation with elan-Interfaces
530 setupElanBroadcastGroups(elanInfo, interfaceInfo.getDpId());
532 setupLocalBroadcastGroups(elanInfo, interfaceInfo);
533 //Terminating Service , UnknownDMAC Table.
534 setupTerminateServiceTable(elanInfo, interfaceInfo);
535 ElanUtils.setupTermDmacFlows(interfaceInfo, mdsalManager);
536 setupUnknownDMacTable(elanInfo, interfaceInfo);
537 setupFilterEqualsTable(elanInfo, interfaceInfo);
538 // bind the Elan service to the Interface
539 bindService(elanInfo, interfaceInfo.getInterfaceName());
541 //update the remote-DPNs remoteBC group entry with Tunnels
542 setElanBCGrouponOtherDpns(elanInfo, interfaceInfo);
546 public void setupFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
547 int ifTag = interfaceInfo.getInterfaceTag();
548 Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, ifTag),
549 9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
551 mdsalManager.installFlow(interfaceInfo.getDpId(), flow);
553 Flow flowEntry = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, 1000+ifTag),
554 10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag),
555 MDSALUtil.buildInstructionsDrop());
557 mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntry);
560 public void removeFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
561 int ifTag = interfaceInfo.getInterfaceTag();
562 Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, ifTag),
563 9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
565 mdsalManager.removeFlow(interfaceInfo.getDpId(), flow);
567 Flow flowEntity = MDSALUtil.buildFlowNew(ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, 1000+ifTag),
568 10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag),
569 MDSALUtil.buildInstructionsDrop());
571 mdsalManager.removeFlow(interfaceInfo.getDpId(), flowEntity);
574 private List<Bucket> getRemoteBCGroupBucketInfos(ElanInstance elanInfo,
575 int bucketKeyStart, InterfaceInfo interfaceInfo) {
576 BigInteger dpnId = interfaceInfo.getDpId();
577 int elanTag = elanInfo.getElanTag().intValue();
578 int bucketId = bucketKeyStart;
579 List<Bucket> listBuckets = new ArrayList<Bucket>();
580 ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
581 if(elanDpns != null) {
582 List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
583 for(DpnInterfaces dpnInterface : dpnInterfaceses) {
584 if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
586 List<Action> listAction = ElanUtils.getInternalItmEgressAction(dpnId, dpnInterface.getDpId(), elanTag);
587 listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
589 } catch (Exception ex) {
590 logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() );
594 List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId);
595 listBuckets.addAll(elanL2GwDevicesBuckets);
600 private List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo, BigInteger dpnId, int bucketId) {
601 int elanTag = elanInfo.getElanTag().intValue();
602 List<Bucket> listBucketInfo = new ArrayList<Bucket>();
603 ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
604 if(elanDpns != null) {
605 List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
606 for(DpnInterfaces dpnInterface : dpnInterfaceses) {
607 if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
609 List<Action> listActionInfo = ElanUtils.getInternalItmEgressAction(dpnId, dpnInterface.getDpId(), elanTag);
610 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, 0, bucketId, 0xffffffffL, 0xffffffffL));
612 } catch (Exception ex) {
613 logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() );
618 List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId);
619 listBucketInfo.addAll(elanL2GwDevicesBuckets);
621 return listBucketInfo;
624 private void setElanBCGrouponOtherDpns(ElanInstance elanInfo,
625 InterfaceInfo interfaceInfo) {
626 BigInteger dpnId = interfaceInfo.getDpId();
627 int elanTag = elanInfo.getElanTag().intValue();
628 long groupId = ElanUtils.getElanRemoteBCGID(elanTag);
629 List<Bucket> listBucket = new ArrayList<Bucket>();
631 ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
632 if(elanDpns != null) {
633 List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
634 for(DpnInterfaces dpnInterface : dpnInterfaceses) {
635 List<Bucket> remoteListBucketInfo = new ArrayList<Bucket>();
636 if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && !dpnInterface.getDpId().equals(dpnId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
637 for(String ifName : dpnInterface.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 listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
648 remoteListBucketInfo.addAll(listBucket);
649 for(DpnInterfaces otherFes : dpnInterfaceses) {
650 if (ElanUtils.isDpnPresent(otherFes.getDpId()) && otherFes.getDpId() != dpnInterface.getDpId()
651 && otherFes.getInterfaces() != null && ! otherFes.getInterfaces().isEmpty()) {
653 List<Action> remoteListActionInfo = ElanUtils.getInternalItmEgressAction(dpnInterface.getDpId(), otherFes.getDpId(), elanTag);
654 remoteListBucketInfo.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,MDSALUtil.WATCH_GROUP));
656 } catch (Exception ex) {
657 logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnInterface.getDpId(), otherFes.getDpId() );
662 List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId,
664 remoteListBucketInfo.addAll(elanL2GwDevicesBuckets);
666 if (remoteListBucketInfo.size() == 0) {
667 logger.debug( "No ITM is present on Dpn - {} " ,dpnInterface.getDpId());
670 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(remoteListBucketInfo));
671 mdsalManager.syncInstallGroup(dpnInterface.getDpId(), group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
678 * Returns the bucket info with the given interface as the only bucket.
680 private Bucket getLocalBCGroupBucketInfo(InterfaceInfo interfaceInfo, int bucketIdStart) {
681 return MDSALUtil.buildBucket(getInterfacePortActions(interfaceInfo), MDSALUtil.GROUP_WEIGHT, bucketIdStart, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP);
684 private List<MatchInfo> getMatchesForElanTag(Long elanTag) {
685 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
687 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
688 ElanUtils.getElanMetadataLabel(elanTag),
689 MetaDataUtil.METADATA_MASK_SERVICE }));
694 private List<MatchInfo> buildMatchesForVni(Long vni) {
695 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
696 MatchInfo match = new MatchInfo(MatchFieldType.tunnel_id,
697 new BigInteger[]{BigInteger.valueOf(vni)} );
698 mkMatches.add(match);
702 private List<Instruction> getInstructionsForOutGroup(
704 List<Instruction> mkInstructions = new ArrayList<Instruction>();
705 List <Action> actions = new ArrayList <Action> ();
706 actions.add(new ActionInfo(ActionType.group, new String[]{Long.toString(groupId)}).buildAction());
707 mkInstructions.add(MDSALUtil.getWriteActionsInstruction(actions, 0));
708 return mkInstructions;
711 private List<MatchInfo> getMatchesForElanTag(long elanTag, boolean isSHFlagSet) {
712 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
714 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
715 ElanUtils.getElanMetadataLabel(elanTag, isSHFlagSet),
716 MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG}));
724 * Builds the list of instructions to be installed in the External Tunnel table (38), which so far
725 * consists in writing the elanTag in metadata and send packet to the new DHCP table
727 * @param elanTag elanTag to be written in metadata when flow is selected
728 * @return the instructions ready to be installed in a flow
730 private List<InstructionInfo> getInstructionsExtTunnelTable(Long elanTag) {
731 List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
732 mkInstructions.add(new InstructionInfo(InstructionType.write_metadata,
734 ElanUtils.getElanMetadataLabel(elanTag),
735 ElanUtils.getElanMetadataMask()
737 // TODO (eperefr) We should point to SMAC or DMAC depending on a configuration property to enable
739 mkInstructions.add(new InstructionInfo(InstructionType.goto_table,
740 new long[] { ElanConstants.ELAN_DMAC_TABLE }));
742 return mkInstructions;
745 public void removeFlowsAndGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
746 removeStaticELanFlows(elanInfo, interfaceInfo);
747 unbindService(elanInfo, interfaceInfo.getInterfaceName());
750 public void installMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
752 String interfaceName = interfaceInfo.getInterfaceName();
753 BigInteger currentDpn = interfaceInfo.getDpId();
754 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
755 if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
756 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
757 for(MacEntry macEntry : macEntries) {
758 PhysAddress physAddress = macEntry.getMacAddress();
759 ElanUtils.setupMacFlows(elanInfo,
761 macEntry.isIsStaticAddress()
762 ? ElanConstants.STATIC_MAC_TIMEOUT
763 : elanInfo.getMacTimeout(), physAddress.getValue());
765 //Programming the remoteDMACFlows
766 ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
767 List<DpnInterfaces> dpnInterfaceLists = elanDpnInterfacesList.getDpnInterfaces();
768 for(DpnInterfaces dpnInterfaces : dpnInterfaceLists){
769 if(dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) {
772 List<String> remoteElanInterfaces = dpnInterfaces.getInterfaces();
773 for(String remoteIf : remoteElanInterfaces) {
774 ElanInterfaceMac elanIfMac = ElanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
775 InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf);
776 if(elanIfMac == null) {
779 List<MacEntry> remoteMacEntries = elanIfMac.getMacEntry();
780 if(remoteMacEntries != null) {
781 for (MacEntry macEntry : remoteMacEntries) {
782 PhysAddress physAddress = macEntry.getMacAddress();
783 ElanUtils.installDmacFlowsToInternalRemoteMac(currentDpn, remoteInterface.getDpId(),
784 remoteInterface.getInterfaceTag(),
785 elanInfo.getElanTag(),
786 physAddress.getValue(),
787 elanInfo.getElanInstanceName());
795 // Install DMAC entry on dst DPN
796 public void installDMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId) {
797 String interfaceName = interfaceInfo.getInterfaceName();
798 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
799 if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
800 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
801 for(MacEntry macEntry : macEntries) {
802 PhysAddress physAddress = macEntry.getMacAddress();
803 ElanUtils.setupDMacFlowonRemoteDpn(elanInfo, interfaceInfo, dstDpId, physAddress.getValue());
808 public void removeMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
809 ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceInfo.getInterfaceName());
810 if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
811 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
812 for(MacEntry macEntry : macEntries) {
813 ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry);
818 public void setupElanBroadcastGroups(ElanInstance elanInfo, BigInteger dpnId) {
819 List<Bucket> listBucket = new ArrayList<Bucket>();
821 long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag());
823 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpnId);
824 for(String ifName : dpnInterfaces.getInterfaces()) {
825 // In case if there is a InterfacePort in the cache which is not in
826 // operational state, skip processing it
827 // FIXME: interfaceType to be obtained dynamically. It doesn't
828 // affect the functionality here as it is nowhere used.
829 InterfaceType interfaceType = InterfaceInfo.InterfaceType.VLAN_INTERFACE;
830 InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceType);
831 if (!isOperational(ifInfo)) {
835 listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
838 List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnId, bucketId);
839 listBucket.addAll(listBucketInfoRemote);
841 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket));
842 logger.trace("installing the remote BroadCast Group:{}", group);
843 mdsalManager.syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
846 public void setupLocalBroadcastGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
847 List<Bucket> listBucket = new ArrayList<Bucket>();
849 BigInteger dpnId = interfaceInfo.getDpId();
850 long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
852 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpnId);
853 for(String ifName : dpnInterfaces.getInterfaces()) {
854 // In case if there is a InterfacePort in the cache which is not in
855 // operational state, skip processing it
856 InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType());
857 if (!isOperational(ifInfo)) {
861 listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
865 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket));
866 logger.trace("installing the localBroadCast Group:{}", group);
867 mdsalManager.syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
870 public void removeLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
871 BigInteger dpnId = interfaceInfo.getDpId();
872 long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
873 List<Bucket> listBuckets = new ArrayList<>();
875 listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
876 //listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, 1, interfaceInfo));
877 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets));
878 logger.trace("deleted the localBroadCast Group:{}", group);
879 mdsalManager.syncRemoveGroup(dpnId, group);
882 public void removeElanBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
884 List<Bucket> listBuckets = new ArrayList<>();
885 listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
887 listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo));
888 BigInteger dpnId = interfaceInfo.getDpId();
889 long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag());
890 Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets));
891 logger.trace("deleting the remoteBroadCast group:{}", group);
892 mdsalManager.syncRemoveGroup(dpnId, group);
896 * Installs a flow in the External Tunnel table consisting in translating
897 * the VNI retrieved from the packet that came over a tunnel with a TOR into
898 * elanTag that will be used later in the ELANs pipeline.
905 public void setExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
906 long elanTag = elanInfo.getElanTag();
907 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId,
908 NwConstants.EXTERNAL_TUNNEL_TABLE,
909 getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanTag),
911 elanInfo.getElanInstanceName(), // flowName
914 ITMConstants.COOKIE_ITM_EXTERNAL.add(BigInteger.valueOf(elanTag)),
915 buildMatchesForVni(elanInfo.getVni()),
916 getInstructionsExtTunnelTable(elanTag) );
918 mdsalManager.installFlow(flowEntity);
922 * Removes, from External Tunnel table, the flow that translates from VNI to elanTag.
923 * Important: ensure this method is only called whenever there is no other ElanInterface in the specified DPN
925 * @param dpnId DPN whose Ext Tunnel table is going to be modified
926 * @param elanInfo holds the elanTag needed for selecting the flow to be removed
928 public void unsetExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
929 // TODO (eperefr): Use DataStoreJobCoordinator in order to avoid that removing the last ElanInstance plus
930 // adding a new one does (almost at the same time) are executed in that exact order
932 String flowId = getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanInfo.getElanTag());
933 FlowEntity flowEntity = new FlowEntity(dpnId);
934 flowEntity.setTableId(NwConstants.EXTERNAL_TUNNEL_TABLE);
935 flowEntity.setFlowId(flowId);
936 mdsalManager.removeFlow(flowEntity);
939 public void setupTerminateServiceTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
940 long elanTag = elanInfo.getElanTag();
941 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE, getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, elanTag),
942 5, String.format("%s:%d","ITM Flow Entry ",elanTag), 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)), ElanUtils.getTunnelMatchesForServiceId((int)elanTag),
943 getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
945 mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity);
948 public void setupUnknownDMacTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
949 long elanTag = elanInfo.getElanTag();
950 Flow flowEntity = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, /*SH flag*/false),
951 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag, /*SH flag*/false),
952 getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGID(elanTag)));
954 mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity);
956 // only if vni is present in elanInfo, perform the following
957 if (elanInfo.getVni() != null && elanInfo.getVni() != 0) {
958 Flow flowEntity2 = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, /*SH flag*/true),
959 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag, /*SH flag*/true),
960 getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
961 mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity2);
967 private void removeStaticELanFlows(final ElanInstance elanInfo, final InterfaceInfo interfaceInfo) {
968 BigInteger dpId = interfaceInfo.getDpId();
970 * If there are not elan ports, remove the unknown smac and default dmac
973 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpId);
974 if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null || dpnInterfaces.getInterfaces().isEmpty()) {
975 // No more Elan Interfaces in this DPN
976 logger.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId);
977 removeDefaultTermFlow(dpId, elanInfo.getElanTag());
978 removeDefaultTermFlow(dpId, interfaceInfo.getInterfaceTag());
979 removeUnknownDmacFlow(dpId, elanInfo);
980 removeElanBroadcastGroup(elanInfo, interfaceInfo);
981 removeLocalBroadcastGroup(elanInfo, interfaceInfo);
982 if ( elanInfo.getVni() != null && elanInfo.getVni().longValue() != 0 ) {
983 unsetExternalTunnelTable(dpId, elanInfo);
985 removeFilterEqualsTable(elanInfo, interfaceInfo);
987 setupElanBroadcastGroups(elanInfo, dpId);
988 setupLocalBroadcastGroups(elanInfo, interfaceInfo);
989 removeFilterEqualsTable(elanInfo, interfaceInfo);
993 private void removeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo) {
994 // Flow flow = getUnknownDmacFlowEntity(dpId, elanInfo);
995 // mdsalManager.removeFlow(dpId, flow);
996 Flow flow = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE,
997 elanInfo.getElanTag(), /*SH flag*/ false)))
998 .setTableId(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE)
1000 mdsalManager.removeFlow(dpId, flow);
1002 if ( elanInfo.getVni() != null && elanInfo.getVni() > 0 ) {
1003 Flow flow2 = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE,
1004 elanInfo.getElanTag(), /*SH flag*/ true)))
1005 .setTableId(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE)
1007 mdsalManager.removeFlow(dpId, flow2);
1013 private void removeDefaultTermFlow(BigInteger dpId, long elanTag) {
1014 ElanUtils.removeTerminatingServiceAction(dpId, (int) elanTag);
1017 private void bindService(ElanInstance elanInfo, String interfaceName) {
1018 // interfaceManager.bindService(interfaceName, ElanUtils.getServiceInfo(elanInfo.getElanInstanceName(), elanInfo.getElanTag(), interfaceName));
1020 int priority = ElanConstants.ELAN_SERVICE_PRIORITY;
1021 int instructionKey = 0;
1022 List<Instruction> instructions = new ArrayList<Instruction>();
1023 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(ElanUtils.getElanMetadataLabel(elanInfo.getElanTag()), MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey));
1024 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(ElanConstants.ELAN_SMAC_TABLE, ++instructionKey));
1027 ElanUtils.getBoundServices(String.format("%s.%s.%s", "vpn",elanInfo.getElanInstanceName(), interfaceName),
1028 ElanConstants.ELAN_SERVICE_INDEX, priority,
1029 ElanConstants.COOKIE_ELAN_INGRESS_TABLE, instructions);
1030 ElanUtils.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
1031 ElanUtils.buildServiceId(interfaceName, ElanConstants.ELAN_SERVICE_INDEX), serviceInfo);
1034 private void unbindService(ElanInstance elanInfo, String interfaceName) {
1035 ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
1036 ElanUtils.buildServiceId(interfaceName,ElanConstants.ELAN_SERVICE_INDEX),
1037 ElanUtils.DEFAULT_CALLBACK);
1040 private void unbindService(ElanInstance elanInfo, String interfaceName, int vlanId) {
1041 ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
1042 ElanUtils.buildServiceId(interfaceName,ElanConstants.ELAN_SERVICE_INDEX),
1043 ElanUtils.DEFAULT_CALLBACK);
1046 private String getFlowRef(long tableId, long elanTag) {
1047 return new StringBuffer().append(tableId).append(elanTag).toString();
1050 private String getUnknownDmacFlowRef(long tableId, long elanTag, boolean shFlag) {
1051 return new StringBuffer().append(tableId).append(elanTag).append(shFlag).toString();
1054 private List<Action> getInterfacePortActions(InterfaceInfo interfaceInfo) {
1055 List<Action> listAction = new ArrayList<Action>();
1057 listAction.add((new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {BigInteger.valueOf(interfaceInfo.getInterfaceTag())}, actionKey)).buildAction());
1059 listAction.add((new ActionInfo(ActionType.nx_resubmit,
1060 new String[] {String.valueOf(ElanConstants.ELAN_FILTER_EQUALS_TABLE)}, actionKey)).buildAction());
1064 private void updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId, List<String> interfaceNames) {
1065 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
1066 .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
1067 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
1072 * Delete elan dpn interface from operational DS.
1074 * @param elanInstanceName
1075 * the elan instance name
1079 private void deleteElanDpnInterface(String elanInstanceName, BigInteger dpId) {
1080 MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL,
1081 ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId));
1084 private List<String> createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId) {
1085 List<String> interfaceNames = new ArrayList<String>();
1086 interfaceNames.add(interfaceName);
1087 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
1088 .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
1089 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
1091 return interfaceNames;
1094 private void createElanInterfaceTablesList(String interfaceName) {
1095 InstanceIdentifier<ElanInterfaceMac> elanInterfaceMacTables = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
1096 Optional<ElanInterfaceMac> interfaceMacTables = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceMacTables);
1097 // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries..
1098 if(!interfaceMacTables.isPresent()) {
1099 ElanInterfaceMac elanInterfaceMacTable = new ElanInterfaceMacBuilder().setElanInterface(interfaceName).setKey(new ElanInterfaceMacKey(interfaceName)).build();
1100 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName),
1101 elanInterfaceMacTable);
1105 private void createElanStateList(String elanInstanceName, String interfaceName) {
1106 InstanceIdentifier<Elan> elanInstance = ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName);
1107 Optional<Elan> elanInterfaceLists = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInstance);
1108 // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries..
1109 if(elanInterfaceLists.isPresent()) {
1110 List<String> interfaceLists = elanInterfaceLists.get().getElanInterfaces();
1111 if(interfaceLists == null) {
1112 interfaceLists = new ArrayList<>();
1114 interfaceLists.add(interfaceName);
1115 Elan elanState = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(interfaceLists).setKey(new ElanKey(elanInstanceName)).build();
1116 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName), elanState);
1120 private boolean isOperational(InterfaceInfo interfaceInfo) {
1121 if (interfaceInfo == null) {
1124 return interfaceInfo.getAdminState() == InterfaceInfo.InterfaceAdminState.ENABLED;
1127 protected void updatedIfPrimaryAttributeChanged(ElanInterface elanInterface, boolean isUpdated) {
1128 String interfaceName = elanInterface.getName();
1129 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
1130 BigInteger dpId = interfaceInfo.getDpId();
1131 InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
1132 Optional<ElanInterfaceMac> existingElanInterface = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
1133 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanInterface.getElanInstanceName());
1135 if(!existingElanInterface.isPresent()) {
1139 List<MacEntry> macEntries = existingElanInterface.get().getMacEntry();
1140 if(macEntries != null && !macEntries.isEmpty()) {
1141 for (MacEntry macEntry : macEntries) {
1143 ElanUtils.setupMacFlows(elanInfo, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, macEntry.getMacAddress().getValue());
1145 ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry);
1150 InstanceIdentifier<DpnInterfaces> dpnInterfaceId = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInterface.getElanInstanceName(), interfaceInfo.getDpId());
1151 Optional<DpnInterfaces> dpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, dpnInterfaceId);
1152 List<String> interfaceLists = dpnInterfaces.get().getInterfaces();
1155 interfaceLists.add(elanInterface.getName());
1157 interfaceLists.remove(elanInterface.getName());
1160 DpnInterfaces updateDpnInterfaces = new DpnInterfacesBuilder().setInterfaces(interfaceLists).setDpId(dpId).setKey(new DpnInterfacesKey(dpId)).build();
1161 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, dpnInterfaceId, updateDpnInterfaces);
1164 installFlowsAndGroups(elanInfo, interfaceInfo);
1166 removeStaticELanFlows(elanInfo, interfaceInfo);
1167 unbindService(elanInfo, interfaceName);
1171 public void handleInternalTunnelStateEvent(BigInteger srcDpId, BigInteger dstDpId) {
1172 ElanDpnInterfaces dpnInterfaceLists = ElanUtils.getElanDpnInterfacesList();
1173 if(dpnInterfaceLists == null) {
1176 List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
1177 for(ElanDpnInterfacesList elanDpns: elanDpnIf) {
1179 String elanName = elanDpns.getElanInstanceName();
1180 List<DpnInterfaces> dpnInterfaces = elanDpns.getDpnInterfaces();
1181 if(dpnInterfaces == null) {
1184 for (DpnInterfaces dpnIf : dpnInterfaces) {
1185 if(dpnIf.getDpId().equals(srcDpId) || dpnIf.getDpId().equals(dstDpId)) {
1190 logger.debug("Elan instance:{} is present b/w srcDpn:{} and dstDpn:{}", elanName, srcDpId, dstDpId);
1191 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanName);
1192 // update Remote BC Group
1193 setupElanBroadcastGroups(elanInfo, srcDpId);
1195 DpnInterfaces dpnInterface = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, srcDpId);
1196 Set<String> interfaceLists = new HashSet<>();
1197 interfaceLists.addAll(dpnInterface.getInterfaces());
1198 for(String ifName : interfaceLists) {
1199 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(ifName);
1200 if (isOperational(interfaceInfo)) {
1201 elanInterfaceManager.installDMacAddressTables(elanInfo, interfaceInfo, dstDpId);
1210 * Handle external tunnel state event.
1212 * @param externalTunnel
1213 * the external tunnel
1217 public void handleExternalTunnelStateEvent(ExternalTunnel externalTunnel, Interface intrf) {
1218 if (!validateExternalTunnelStateEvent(externalTunnel, intrf)) {
1221 // dpId/externalNodeId will be available either in source or destination
1222 // based on the tunnel end point
1223 BigInteger dpId = null;
1224 NodeId externalNodeId = null;
1225 if (StringUtils.isNumeric(externalTunnel.getSourceDevice())) {
1226 dpId = new BigInteger(externalTunnel.getSourceDevice());
1227 externalNodeId = new NodeId(externalTunnel.getDestinationDevice());
1228 } else if (StringUtils.isNumeric(externalTunnel.getDestinationDevice())) {
1229 dpId = new BigInteger(externalTunnel.getDestinationDevice());
1230 externalNodeId = new NodeId(externalTunnel.getSourceDevice());
1232 if (dpId == null || externalNodeId == null) {
1233 logger.error("Dp ID / externalNodeId not found in external tunnel {}", externalTunnel);
1237 ElanDpnInterfaces dpnInterfaceLists = ElanUtils.getElanDpnInterfacesList();
1238 if (dpnInterfaceLists == null) {
1241 List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
1242 for (ElanDpnInterfacesList elanDpns : elanDpnIf) {
1243 String elanName = elanDpns.getElanInstanceName();
1244 ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanName);
1246 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
1247 if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null
1248 || dpnInterfaces.getInterfaces().isEmpty()) {
1251 logger.debug("Elan instance:{} is present in Dpn:{} ", elanName, dpId);
1253 setupElanBroadcastGroups(elanInfo, dpId);
1254 // install L2gwDevices local macs in dpn.
1255 ElanL2GatewayUtils.installL2gwDeviceMacsInDpn(dpId, externalNodeId, elanInfo);
1256 // Install dpn macs on external device
1257 ElanL2GatewayUtils.installDpnMacsInL2gwDevice(elanName, new HashSet<>(dpnInterfaces.getInterfaces()), dpId,
1260 logger.info("Handled ExternalTunnelStateEvent for {}", externalTunnel);
1264 * Validate external tunnel state event.
1266 * @param externalTunnel
1267 * the external tunnel
1270 * @return true, if successful
1272 private boolean validateExternalTunnelStateEvent(ExternalTunnel externalTunnel, Interface intrf) {
1273 if (intrf.getOperStatus() == Interface.OperStatus.Up) {
1274 String srcDevice = externalTunnel.getDestinationDevice();
1275 String destDevice = externalTunnel.getSourceDevice();
1276 ExternalTunnel otherEndPointExtTunnel = ElanUtils.getExternalTunnel(srcDevice, destDevice,
1277 LogicalDatastoreType.CONFIGURATION);
1278 if (logger.isTraceEnabled()) {
1279 logger.trace("Validating external tunnel state: src tunnel {}, dest tunnel {}", externalTunnel,
1280 otherEndPointExtTunnel);
1282 if (otherEndPointExtTunnel != null) {
1283 boolean otherEndPointInterfaceOperational = ElanUtils
1284 .isInterfaceOperational(otherEndPointExtTunnel.getTunnelInterfaceName(), broker);
1285 if (otherEndPointInterfaceOperational) {
1288 logger.debug("Other end [{}] of the external tunnel is not yet UP for {}",
1289 otherEndPointExtTunnel.getTunnelInterfaceName(), externalTunnel);
1296 public void handleInterfaceUpdated(InterfaceInfo interfaceInfo, ElanInstance elanInstance, boolean isStateUp) {
1297 BigInteger dpId = interfaceInfo.getDpId();
1298 String elanName = elanInstance.getElanInstanceName();
1299 String ifName = interfaceInfo.getInterfaceName();
1300 logger.trace("Handling interface update event for interface with info {} , state {}", interfaceInfo, isStateUp);
1303 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
1304 if(dpnInterfaces == null) {
1305 createElanInterfacesList(elanName, interfaceInfo.getInterfaceName(), dpId);
1307 List<String> dpnElanInterfaces = dpnInterfaces.getInterfaces();
1308 dpnElanInterfaces.add(interfaceInfo.getInterfaceName());
1309 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
1310 .setInterfaces(dpnElanInterfaces).setKey(new DpnInterfacesKey(dpId)).build();
1311 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanName, interfaceInfo.getDpId()), dpnInterface);
1314 logger.trace("ElanInterface Service is installed for interface:{}", ifName);
1315 elanInterfaceManager.installFlowsAndGroups(elanInstance, interfaceInfo);
1316 elanInterfaceManager.installMacAddressTables(elanInstance, interfaceInfo);
1318 if (elanInstance.getVni() != null && elanInstance.getVni() != 0) {
1319 List<PhysAddress> macAddresses = ElanUtils
1320 .getElanInterfaceMacAddresses(interfaceInfo.getInterfaceName());
1321 if (macAddresses != null && !macAddresses.isEmpty()) {
1322 ElanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(),
1323 dpId, macAddresses);
1328 DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
1329 if(dpnInterfaces != null) {
1330 List<String> dpnElanInterfaces = dpnInterfaces.getInterfaces();
1331 dpnElanInterfaces.remove(interfaceInfo.getInterfaceName());
1332 DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
1333 .setInterfaces(dpnElanInterfaces).setKey(new DpnInterfacesKey(dpId)).build();
1334 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanName, interfaceInfo.getDpId()), dpnInterface);
1336 logger.trace("ElanInterface Service is removed for the interface:{}", ifName);
1337 elanInterfaceManager.removeMacAddressTables(elanInstance, interfaceInfo);
1338 elanInterfaceManager.removeFlowsAndGroups(elanInstance, interfaceInfo);
1340 // Removing MACs from External Devices belonging to this ELAN
1341 if (elanInstance.getVni() != null && elanInstance.getVni() != 0) {
1342 List<PhysAddress> macAddresses = ElanUtils
1343 .getElanInterfaceMacAddresses(interfaceInfo.getInterfaceName());
1344 if (macAddresses != null && !macAddresses.isEmpty()) {
1345 ElanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInstance, macAddresses);
1351 private List<MatchInfo> getMatchesForFilterEqualsLPortTag(int LportTag) {
1352 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1353 // Matching metadata
1354 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
1355 MetaDataUtil.getLportTagMetaData(LportTag),
1356 MetaDataUtil.METADATA_MASK_LPORT_TAG }));
1357 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(LportTag)}));
1362 private List<MatchInfo> getTunnelIdMatchForFilterEqualsLPortTag(int LportTag) {
1363 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1364 // Matching metadata
1365 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
1366 BigInteger.valueOf(LportTag)}));
1370 public void updateRemoteBroadcastGroupForAllElanDpns(ElanInstance elanInfo) {
1371 List<DpnInterfaces> dpns = ElanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName());
1375 for (DpnInterfaces dpn : dpns) {
1376 setupElanBroadcastGroups(elanInfo, dpn.getDpId());
1380 public static List<Bucket> getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, BigInteger dpnId,
1382 List<Bucket> listBucketInfo = new ArrayList<Bucket>();
1383 ConcurrentMap<String, L2GatewayDevice> map = ElanL2GwCacheUtils
1384 .getInvolvedL2GwDevices(elanInfo.getElanInstanceName());
1385 for (L2GatewayDevice device : map.values()) {
1386 String interfaceName = ElanL2GatewayUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
1387 device.getHwvtepNodeId());
1388 if (interfaceName == null) {
1391 List<Action> listActionInfo = ElanUtils.buildItmEgressActions(interfaceName, elanInfo.getVni());
1392 listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
1393 MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
1396 return listBucketInfo;