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
9 package org.opendaylight.netvirt.elan.internal;
11 import com.google.common.base.Optional;
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.HashSet;
18 import java.util.List;
21 import java.util.concurrent.Future;
22 import java.util.function.BiFunction;
23 import javax.inject.Inject;
24 import javax.inject.Singleton;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
27 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.genius.interfacemanager.exceptions.InterfaceAlreadyExistsException;
30 import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
31 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
32 import org.opendaylight.genius.mdsalutil.MDSALUtil;
33 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
34 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
35 import org.opendaylight.genius.mdsalutil.NwConstants;
36 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
37 import org.opendaylight.genius.utils.ServiceIndex;
38 import org.opendaylight.genius.utils.clustering.EntityOwnerUtils;
39 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
40 import org.opendaylight.infrautils.inject.AbstractLifecycle;
41 import org.opendaylight.netvirt.elan.statusanddiag.ElanStatusMonitor;
42 import org.opendaylight.netvirt.elan.utils.ElanConstants;
43 import org.opendaylight.netvirt.elan.utils.ElanUtils;
44 import org.opendaylight.netvirt.elanmanager.api.IElanService;
45 import org.opendaylight.netvirt.elanmanager.exceptions.MacNotFoundException;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstance;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstanceBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface.EtreeInterfaceType;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterfaceBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntries;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntriesBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.Elan;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
72 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
73 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
74 import org.opendaylight.yangtools.yang.common.RpcResult;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
79 public class ElanServiceProvider extends AbstractLifecycle implements IElanService {
81 private static final Logger LOG = LoggerFactory.getLogger(ElanServiceProvider.class);
83 private final IdManagerService idManager;
84 private final IInterfaceManager interfaceManager;
85 private final ElanInstanceManager elanInstanceManager;
86 private final ElanBridgeManager bridgeMgr;
87 private final DataBroker broker;
88 private final ElanStatusMonitor elanStatusMonitor;
89 private final ElanUtils elanUtils;
91 private boolean generateIntBridgeMac = true;
92 private boolean isL2BeforeL3;
95 public ElanServiceProvider(IdManagerService idManager, IInterfaceManager interfaceManager,
96 ElanInstanceManager elanInstanceManager, ElanBridgeManager bridgeMgr,
97 DataBroker dataBroker,
98 ElanInterfaceManager elanInterfaceManager,
99 ElanStatusMonitor elanStatusMonitor, ElanUtils elanUtils,
100 EntityOwnershipService entityOwnershipService) {
101 this.idManager = idManager;
102 this.interfaceManager = interfaceManager;
103 this.elanInstanceManager = elanInstanceManager;
104 this.bridgeMgr = bridgeMgr;
105 this.broker = dataBroker;
106 this.elanStatusMonitor = elanStatusMonitor;
107 this.elanUtils = elanUtils;
108 elanInterfaceManager.setElanUtils(elanUtils);
110 EntityOwnerUtils.registerEntityCandidateForOwnerShip(entityOwnershipService,
111 HwvtepSouthboundConstants.ELAN_ENTITY_TYPE, HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
113 } catch (CandidateAlreadyRegisteredException e) {
114 LOG.error("failed to register the entity");
119 @SuppressWarnings("checkstyle:IllegalCatch")
120 protected void start() throws Exception {
121 LOG.info("Starting ElnaServiceProvider");
122 elanStatusMonitor.reportStatus("STARTING");
126 elanStatusMonitor.reportStatus("OPERATIONAL");
127 } catch (Exception e) {
128 elanStatusMonitor.reportStatus("ERROR");
134 protected void stop() throws Exception {
137 private void createIdPool() throws Exception {
138 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder().setPoolName(ElanConstants.ELAN_ID_POOL_NAME)
139 .setLow(ElanConstants.ELAN_ID_LOW_VALUE).setHigh(ElanConstants.ELAN_ID_HIGH_VALUE).build();
140 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
141 if (result != null && result.get().isSuccessful()) {
142 LOG.debug("ELAN Id Pool is created successfully");
147 public boolean createElanInstance(String elanInstanceName, long macTimeout, String description) {
148 ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName);
149 boolean isSuccess = true;
150 if (existingElanInstance != null) {
151 if (compareWithExistingElanInstance(existingElanInstance, macTimeout, description)) {
152 LOG.debug("Elan Instance is already present in the Operational DS {}", existingElanInstance);
155 ElanInstance updateElanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
156 .setDescription(description).setMacTimeout(macTimeout)
157 .setKey(new ElanInstanceKey(elanInstanceName)).build();
158 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
159 ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName), updateElanInstance);
160 LOG.debug("Updating the Elan Instance {} with MAC TIME-OUT %l and Description %s ",
161 updateElanInstance, macTimeout, description);
164 ElanInstance elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
165 .setMacTimeout(macTimeout).setDescription(description).setKey(new ElanInstanceKey(elanInstanceName))
167 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
168 ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName), elanInstance);
169 LOG.debug("Creating the new Elan Instance {}", elanInstance);
175 public boolean createEtreeInstance(String elanInstanceName, long macTimeout, String description) {
176 ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName);
177 boolean isSuccess = true;
178 if (existingElanInstance != null) {
179 if (compareWithExistingElanInstance(existingElanInstance, macTimeout, description)) {
180 LOG.warn("Etree Instance is already present in the Operational DS {}", existingElanInstance);
183 EtreeInstance etreeInstance = new EtreeInstanceBuilder().build();
184 ElanInstance updateElanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
185 .setDescription(description).setMacTimeout(macTimeout)
186 .setKey(new ElanInstanceKey(elanInstanceName))
187 .addAugmentation(EtreeInstance.class, etreeInstance).build();
188 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
189 ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName), updateElanInstance);
190 LOG.debug("Updating the Etree Instance {} with MAC TIME-OUT %l and Description %s ",
191 updateElanInstance, macTimeout, description);
194 EtreeInstance etreeInstance = new EtreeInstanceBuilder().build();
195 ElanInstance elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
196 .setMacTimeout(macTimeout).setDescription(description).setKey(new ElanInstanceKey(elanInstanceName))
197 .addAugmentation(EtreeInstance.class, etreeInstance).build();
198 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
199 ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName), elanInstance);
200 LOG.debug("Creating the new Etree Instance {}", elanInstance);
206 public EtreeInterface getEtreeInterfaceByElanInterfaceName(String elanInterface) {
207 return ElanUtils.getEtreeInterfaceByElanInterfaceName(broker, elanInterface);
210 public static boolean compareWithExistingElanInstance(ElanInstance existingElanInstance, long macTimeOut,
211 String description) {
212 boolean isEqual = false;
213 if (existingElanInstance.getMacTimeout() == macTimeOut
214 && existingElanInstance.getDescription().equals(description)) {
221 public void updateElanInstance(String elanInstanceName, long newMacTimout, String newDescription) {
222 createElanInstance(elanInstanceName, newMacTimout, newDescription);
226 public boolean deleteEtreeInstance(String etreeInstanceName) {
227 return deleteElanInstance(etreeInstanceName);
231 public boolean deleteElanInstance(String elanInstanceName) {
232 boolean isSuccess = false;
233 ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName);
234 if (existingElanInstance == null) {
235 LOG.debug("Elan Instance is not present {}", existingElanInstance);
238 LOG.debug("Deletion of the existing Elan Instance {}", existingElanInstance);
239 ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
240 ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName));
246 public void addEtreeInterface(String etreeInstanceName, String interfaceName, EtreeInterfaceType interfaceType,
247 List<String> staticMacAddresses, String description) {
248 ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(etreeInstanceName);
249 if (existingElanInstance != null && existingElanInstance.getAugmentation(EtreeInstance.class) != null) {
250 EtreeInterface etreeInterface = new EtreeInterfaceBuilder().setEtreeInterfaceType(interfaceType).build();
251 ElanInterface elanInterface;
252 if (staticMacAddresses == null) {
253 elanInterface = new ElanInterfaceBuilder().setElanInstanceName(etreeInstanceName)
254 .setDescription(description).setName(interfaceName).setKey(new ElanInterfaceKey(interfaceName))
255 .addAugmentation(EtreeInterface.class, etreeInterface).build();
257 List<StaticMacEntries> staticMacEntries = ElanUtils.getStaticMacEntries(staticMacAddresses);
258 elanInterface = new ElanInterfaceBuilder().setElanInstanceName(etreeInstanceName)
259 .setDescription(description).setName(interfaceName)
260 .setStaticMacEntries(staticMacEntries)
261 .setKey(new ElanInterfaceKey(interfaceName))
262 .addAugmentation(EtreeInterface.class, etreeInterface).build();
264 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
265 ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
266 LOG.debug("Creating the new Etree Interface {}", elanInterface);
271 public void addElanInterface(String elanInstanceName, String interfaceName, List<String> staticMacAddresses,
272 String description) {
273 ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName);
274 if (existingElanInstance != null) {
275 ElanInterfaceBuilder elanInterfaceBuilder = new ElanInterfaceBuilder()
276 .setElanInstanceName(elanInstanceName)
277 .setDescription(description).setName(interfaceName)
278 .setKey(new ElanInterfaceKey(interfaceName));
279 if (staticMacAddresses != null) {
280 List<StaticMacEntries> staticMacEntries = ElanUtils.getStaticMacEntries(staticMacAddresses);
281 elanInterfaceBuilder.setStaticMacEntries(staticMacEntries);
283 ElanInterface elanInterface = elanInterfaceBuilder.build();
284 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
285 ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
286 LOG.debug("Created the new ELan Interface {}", elanInterface);
291 public void updateElanInterface(String elanInstanceName, String interfaceName,
292 List<String> updatedStaticMacAddresses, String newDescription) {
293 ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(broker, interfaceName);
294 if (existingElanInterface == null) {
298 List<StaticMacEntries> updatedStaticMacEntries = ElanUtils.getStaticMacEntries(updatedStaticMacAddresses);
299 LOG.debug("updating the ElanInterface with new Mac Entries {}", updatedStaticMacAddresses);
300 ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
301 .setName(interfaceName).setDescription(newDescription).setStaticMacEntries(updatedStaticMacEntries)
302 .setKey(new ElanInterfaceKey(interfaceName)).build();
303 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
304 ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface);
308 public void deleteEtreeInterface(String elanInstanceName, String interfaceName) {
309 deleteElanInterface(elanInstanceName, interfaceName);
310 LOG.debug("deleting the Etree Interface {}", interfaceName);
314 public void deleteElanInterface(String elanInstanceName, String interfaceName) {
315 ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(broker, interfaceName);
316 if (existingElanInterface != null) {
317 ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION,
318 ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName));
319 LOG.debug("deleting the Elan Interface {}", existingElanInterface);
324 public void addStaticMacAddress(String elanInstanceName, String interfaceName, String macAddress) {
325 ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(broker, interfaceName);
326 PhysAddress updateStaticMacAddress = new PhysAddress(macAddress);
327 if (existingElanInterface != null) {
328 StaticMacEntriesBuilder staticMacEntriesBuilder = new StaticMacEntriesBuilder();
329 StaticMacEntries staticMacEntry = staticMacEntriesBuilder.setMacAddress(updateStaticMacAddress).build();
330 InstanceIdentifier<StaticMacEntries> staticMacEntriesIdentifier =
331 ElanUtils.getStaticMacEntriesCfgDataPathIdentifier(interfaceName,
333 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, staticMacEntriesIdentifier, staticMacEntry);
341 public void deleteStaticMacAddress(String elanInstanceName, String interfaceName, String macAddress)
342 throws MacNotFoundException {
343 ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(broker, interfaceName);
344 if (existingElanInterface != null) {
345 InstanceIdentifier<StaticMacEntries> staticMacEntriesIdentifier =
346 ElanUtils.getStaticMacEntriesCfgDataPathIdentifier(interfaceName,
348 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, staticMacEntriesIdentifier);
353 public Collection<MacEntry> getElanMacTable(String elanInstanceName) {
354 Elan elanInfo = ElanUtils.getElanByName(broker, elanInstanceName);
355 List<MacEntry> macAddress = new ArrayList<>();
356 if (elanInfo == null) {
359 List<String> elanInterfaces = elanInfo.getElanInterfaces();
360 if (elanInterfaces != null && elanInterfaces.size() > 0) {
361 for (String elanInterface : elanInterfaces) {
362 ElanInterfaceMac elanInterfaceMac = elanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
363 if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null
364 && elanInterfaceMac.getMacEntry().size() > 0) {
365 macAddress.addAll(elanInterfaceMac.getMacEntry());
373 public void flushMACTable(String elanInstanceName) {
374 Elan elanInfo = ElanUtils.getElanByName(broker, elanInstanceName);
375 if (elanInfo == null) {
378 List<String> elanInterfaces = elanInfo.getElanInterfaces();
379 if (elanInterfaces == null || elanInterfaces.isEmpty()) {
382 for (String elanInterface : elanInterfaces) {
383 ElanInterfaceMac elanInterfaceMac = elanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
384 if (elanInterfaceMac.getMacEntry() != null && elanInterfaceMac.getMacEntry().size() > 0) {
385 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
386 for (MacEntry macEntry : macEntries) {
388 deleteStaticMacAddress(elanInstanceName, elanInterface, macEntry.getMacAddress().getValue());
389 } catch (MacNotFoundException e) {
390 LOG.error("Mac Not Found Exception {}", e);
399 public ElanInstance getElanInstance(String elanName) {
400 return ElanUtils.getElanInstanceByName(broker, elanName);
404 public List<ElanInstance> getElanInstances() {
405 InstanceIdentifier<ElanInstances> elanInstancesIdentifier = InstanceIdentifier.builder(ElanInstances.class)
407 return elanUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanInstancesIdentifier).transform(
408 ElanInstances::getElanInstance).or(Collections.emptyList());
412 public List<String> getElanInterfaces(String elanInstanceName) {
413 List<String> elanInterfaces = new ArrayList<>();
414 InstanceIdentifier<ElanInterfaces> elanInterfacesIdentifier = InstanceIdentifier.builder(ElanInterfaces.class)
416 Optional<ElanInterfaces> elanInterfacesOptional = elanUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
417 elanInterfacesIdentifier);
418 if (!elanInterfacesOptional.isPresent()) {
419 return elanInterfaces;
421 List<ElanInterface> elanInterfaceList = elanInterfacesOptional.get().getElanInterface();
422 for (ElanInterface elanInterface : elanInterfaceList) {
423 if (elanInterface.getElanInstanceName().equals(elanInstanceName)) {
424 elanInterfaces.add(elanInterface.getName());
427 return elanInterfaces;
430 public boolean getGenerateIntBridgeMac() {
431 return generateIntBridgeMac;
434 public void setGenerateIntBridgeMac(boolean generateIntBridgeMac) {
435 this.generateIntBridgeMac = generateIntBridgeMac;
439 public void createExternalElanNetworks(Node node) {
440 handleExternalElanNetworks(node, (elanInstance, interfaceName) -> {
441 createExternalElanNetwork(elanInstance, interfaceName);
447 public void createExternalElanNetwork(ElanInstance elanInstance) {
448 handleExternalElanNetwork(elanInstance, (elanInstance1, interfaceName) -> {
449 createExternalElanNetwork(elanInstance1, interfaceName);
454 private void createExternalElanNetwork(ElanInstance elanInstance, String interfaceName) {
455 if (interfaceName == null) {
456 LOG.trace("No physical interface is attached to {}", elanInstance.getPhysicalNetworkName());
460 String elanInterfaceName = createIetfInterfaces(elanInstance, interfaceName);
461 addElanInterface(elanInstance.getElanInstanceName(), elanInterfaceName, null, null);
465 public void deleteExternalElanNetworks(Node node) {
466 handleExternalElanNetworks(node, (elanInstance, interfaceName) -> {
467 deleteExternalElanNetwork(elanInstance, interfaceName);
473 public void deleteExternalElanNetwork(ElanInstance elanInstance) {
474 handleExternalElanNetwork(elanInstance, (elanInstance1, interfaceName) -> {
475 deleteExternalElanNetwork(elanInstance1, interfaceName);
480 private void deleteExternalElanNetwork(ElanInstance elanInstance, String interfaceName) {
481 if (interfaceName == null) {
482 LOG.trace("No physial interface is attached to {}", elanInstance.getPhysicalNetworkName());
486 String elanInstanceName = elanInstance.getElanInstanceName();
487 for (String elanInterface : getExternalElanInterfaces(elanInstanceName)) {
488 if (elanInterface.startsWith(interfaceName)) {
489 deleteIetfInterface(elanInterface);
490 deleteElanInterface(elanInstanceName, elanInterface);
496 public void updateExternalElanNetworks(Node origNode, Node updatedNode) {
497 if (!bridgeMgr.isIntegrationBridge(updatedNode)) {
501 List<ElanInstance> elanInstances = getElanInstances();
502 if (elanInstances == null || elanInstances.isEmpty()) {
503 LOG.trace("No ELAN instances found");
507 LOG.debug("updateExternalElanNetworks, orig bridge {} . updated bridge {}", origNode, updatedNode);
509 Map<String, String> origProviderMappping = getMapFromOtherConfig(origNode,
510 ElanBridgeManager.PROVIDER_MAPPINGS_KEY);
511 Map<String, String> updatedProviderMappping = getMapFromOtherConfig(updatedNode,
512 ElanBridgeManager.PROVIDER_MAPPINGS_KEY);
514 boolean hasDatapathIdOnOrigNode = bridgeMgr.hasDatapathID(origNode);
515 boolean hasDatapathIdOnUpdatedNode = bridgeMgr.hasDatapathID(updatedNode);
517 for (ElanInstance elanInstance : elanInstances) {
518 String physicalNetworkName = elanInstance.getPhysicalNetworkName();
519 if (physicalNetworkName != null) {
520 String origPortName = origProviderMappping.get(physicalNetworkName);
521 String updatedPortName = updatedProviderMappping.get(physicalNetworkName);
522 if (hasPortNameRemoved(origPortName, updatedPortName)) {
523 deleteExternalElanNetwork(elanInstance,
524 bridgeMgr.getProviderInterfaceName(origNode, physicalNetworkName));
526 if (hasPortNameUpdated(origPortName, updatedPortName)
527 || hasDatapathIdAdded(hasDatapathIdOnOrigNode, hasDatapathIdOnUpdatedNode)) {
528 createExternalElanNetwork(elanInstance,
529 bridgeMgr.getProviderInterfaceName(updatedNode, physicalNetworkName));
535 private boolean hasDatapathIdAdded(boolean hasDatapathIdOnOrigNode, boolean hasDatapathIdOnUpdatedNode) {
536 return !hasDatapathIdOnOrigNode && hasDatapathIdOnUpdatedNode;
539 private boolean hasPortNameUpdated(String origPortName, String updatedPortName) {
540 return updatedPortName != null && !updatedPortName.equals(origPortName);
543 private boolean hasPortNameRemoved(String origPortName, String updatedPortName) {
544 return origPortName != null && !origPortName.equals(updatedPortName);
547 private Map<String, String> getMapFromOtherConfig(Node node, String otherConfigColumn) {
548 return bridgeMgr.getOpenvswitchOtherConfigMap(node, otherConfigColumn);
552 public Collection<String> getExternalElanInterfaces(String elanInstanceName) {
553 List<String> elanInterfaces = getElanInterfaces(elanInstanceName);
554 if (elanInterfaces == null || elanInterfaces.isEmpty()) {
555 LOG.trace("No ELAN interfaces defined for {}", elanInstanceName);
556 return Collections.emptySet();
559 Set<String> externalElanInterfaces = new HashSet<>();
560 for (String elanInterface : elanInterfaces) {
561 if (interfaceManager.isExternalInterface(elanInterface)) {
562 externalElanInterfaces.add(elanInterface);
566 return externalElanInterfaces;
570 public String getExternalElanInterface(String elanInstanceName, BigInteger dpnId) {
571 return elanUtils.getExternalElanInterface(elanInstanceName, dpnId);
575 public boolean isExternalInterface(String interfaceName) {
576 return interfaceManager.isExternalInterface(interfaceName);
580 public ElanInterface getElanInterfaceByElanInterfaceName(String interfaceName) {
581 return ElanUtils.getElanInterfaceByElanInterfaceName(broker, interfaceName);
585 public void handleKnownL3DmacAddress(String macAddress, String elanInstanceName, int addOrRemove) {
587 LOG.trace("ELAN service is after L3VPN in the Netvirt pipeline skip known L3DMAC flows installation");
590 ElanInstance elanInstance = ElanUtils.getElanInstanceByName(broker, elanInstanceName);
591 if (elanInstance == null) {
592 LOG.warn("Null elan instance {}", elanInstanceName);
596 List<BigInteger> dpnsIdsForElanInstance = elanUtils.getParticipatingDpnsInElanInstance(elanInstanceName);
597 if (dpnsIdsForElanInstance == null || dpnsIdsForElanInstance.isEmpty()) {
598 LOG.warn("No DPNs for elan instance {}", elanInstance);
602 elanUtils.handleDmacRedirectToDispatcherFlows(elanInstance.getElanTag(), elanInstanceName, macAddress,
603 addOrRemove, dpnsIdsForElanInstance);
607 public List<MatchInfoBase> getEgressMatchesForElanInstance(String elanInstanceName) {
608 ElanInstance elanInstance = getElanInstance(elanInstanceName);
609 if (elanInstance == null) {
610 LOG.debug("No ELAN instance found for {}", elanInstanceName);
611 return Collections.emptyList();
614 Long elanTag = elanInstance.getElanTag();
615 if (elanTag == null) {
616 LOG.debug("No ELAN tag found for {}", elanInstanceName);
617 return Collections.emptyList();
620 return Collections.singletonList(
621 new NxMatchRegister(ElanConstants.ELAN_REG_ID, elanTag, MetaDataUtil.getElanMaskForReg()));
625 * Create ietf-interfaces based on the ELAN segment type.<br>
626 * For segment type flat - create transparent interface pointing to the
627 * patch-port attached to the physnet port.<br>
628 * For segment type vlan - create trunk interface pointing to the patch-port
629 * attached to the physnet port + trunk-member interface pointing to the
632 * @param elanInstance
635 * parent interface name
636 * @return the name of the interface to be added to the ELAN instance i.e.
637 * trunk-member name for vlan network and transparent for flat
638 * network or null otherwise
640 private String createIetfInterfaces(ElanInstance elanInstance, String parentRef) {
641 String interfaceName = null;
644 if (ElanUtils.isFlat(elanInstance)) {
645 interfaceName = parentRef + IfmConstants.OF_URI_SEPARATOR + "flat";
646 interfaceManager.createVLANInterface(interfaceName, parentRef, null, null, null,
647 IfL2vlan.L2vlanMode.Transparent, true);
648 } else if (ElanUtils.isVlan(elanInstance)) {
649 Long segmentationId = elanInstance.getSegmentationId();
650 interfaceName = parentRef + IfmConstants.OF_URI_SEPARATOR + segmentationId;
651 String trunkName = parentRef + IfmConstants.OF_URI_SEPARATOR + "trunk";
652 // trunk interface may have been created by other vlan network
653 Interface trunkInterface = interfaceManager.getInterfaceInfoFromConfigDataStore(trunkName);
654 if (trunkInterface == null) {
655 interfaceManager.createVLANInterface(trunkName, parentRef, null, null, null,
656 IfL2vlan.L2vlanMode.Trunk, true);
658 interfaceManager.createVLANInterface(interfaceName, trunkName, null, segmentationId.intValue(), null,
659 IfL2vlan.L2vlanMode.TrunkMember, true);
661 } catch (InterfaceAlreadyExistsException e) {
662 LOG.trace("Interface {} was already created", interfaceName);
665 return interfaceName;
668 private void deleteIetfInterface(String interfaceName) {
669 InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
670 InstanceIdentifier<Interface> interfaceInstanceIdentifier = InstanceIdentifier.builder(Interfaces.class)
671 .child(Interface.class, interfaceKey).build();
672 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
673 LOG.debug("Deleting IETF interface {}", interfaceName);
676 private void handleExternalElanNetworks(Node node, BiFunction<ElanInstance, String, Void> function) {
677 if (!bridgeMgr.isIntegrationBridge(node)) {
681 List<ElanInstance> elanInstances = getElanInstances();
682 if (elanInstances == null || elanInstances.isEmpty()) {
683 LOG.trace("No ELAN instances found");
687 for (ElanInstance elanInstance : elanInstances) {
688 String interfaceName = bridgeMgr.getProviderInterfaceName(node, elanInstance.getPhysicalNetworkName());
689 if (interfaceName != null) {
690 function.apply(elanInstance, interfaceName);
695 private void handleExternalElanNetwork(ElanInstance elanInstance, BiFunction<ElanInstance, String, Void> function) {
696 String elanInstanceName = elanInstance.getElanInstanceName();
697 if (elanInstance.getPhysicalNetworkName() == null) {
698 LOG.trace("No physical network attached to {}", elanInstanceName);
702 List<Node> nodes = bridgeMgr.southboundUtils.getOvsdbNodes();
703 if (nodes == null || nodes.isEmpty()) {
704 LOG.trace("No OVS nodes found while creating external network for ELAN {}",
705 elanInstance.getElanInstanceName());
709 for (Node node : nodes) {
710 if (bridgeMgr.isIntegrationBridge(node)) {
711 String interfaceName = bridgeMgr.getProviderInterfaceName(node, elanInstance.getPhysicalNetworkName());
712 function.apply(elanInstance, interfaceName);
717 private void setIsL2BeforeL3() {
718 short elanServiceRealIndex = ServiceIndex.getIndex(NwConstants.ELAN_SERVICE_NAME,
719 NwConstants.ELAN_SERVICE_INDEX);
720 short l3vpnServiceRealIndex = ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME,
721 NwConstants.L3VPN_SERVICE_INDEX);
722 if (elanServiceRealIndex < l3vpnServiceRealIndex) {
723 LOG.info("ELAN service is set before L3VPN service in the Netvirt pipeline");
726 LOG.info("ELAN service is set after L3VPN service in the Netvirt pipeline");
727 isL2BeforeL3 = false;