import org.opendaylight.netvirt.elan.cache.ElanInterfaceCache;
import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
+import org.opendaylight.netvirt.elan.recovery.impl.ElanServiceRecoveryHandler;
import org.opendaylight.netvirt.elan.utils.ElanConstants;
import org.opendaylight.netvirt.elan.utils.ElanEtreeUtils;
import org.opendaylight.netvirt.elan.utils.ElanForwardingEntriesHandler;
import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
+import org.opendaylight.serviceutils.srm.RecoverableListener;
+import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
* @see org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface
*/
@Singleton
-public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanInterface, ElanInterfaceManager> {
+public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanInterface, ElanInterfaceManager>
+ implements RecoverableListener {
private static final Logger LOG = LoggerFactory.getLogger(ElanInterfaceManager.class);
private static final long WAIT_TIME_FOR_SYNC_INSTALL = Long.getLong("wait.time.sync.install", 300L);
private static final boolean SH_FLAG_SET = true;
final ElanUtils elanUtils, final JobCoordinator jobCoordinator,
final ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils,
final ElanInstanceCache elanInstanceCache,
- final ElanInterfaceCache elanInterfaceCache) {
+ final ElanInterfaceCache elanInterfaceCache,
+ final ElanServiceRecoveryHandler elanServiceRecoveryHandler,
+ final ServiceRecoveryRegistry serviceRecoveryRegistry) {
super(ElanInterface.class, ElanInterfaceManager.class);
this.broker = dataBroker;
this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
this.elanL2GatewayMulticastUtils = elanL2GatewayMulticastUtils;
this.elanInstanceCache = elanInstanceCache;
this.elanInterfaceCache = elanInterfaceCache;
+ serviceRecoveryRegistry.addRecoverableListener(elanServiceRecoveryHandler.buildServiceRegistryKey(), this);
}
@Override
@PostConstruct
public void init() {
+ registerListener();
+ }
+
+ @Override
+ public void registerListener() {
registerListener(LogicalDatastoreType.CONFIGURATION, broker);
}
jobCoordinator.enqueueJob(elanInstanceName, configWorker, ElanConstants.JOB_MAX_RETRIES);
}
+ @SuppressWarnings("checkstyle:ForbiddenMethod")
public List<ListenableFuture<Void>> removeElanInterface(ElanInstance elanInfo, String interfaceName,
InterfaceInfo interfaceInfo) {
String elanName = elanInfo.getElanInstanceName();
private void removeLeavesLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
WriteTransaction deleteFlowGroupTx) {
- EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
+ EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class);
if (etreeInstance != null) {
BigInteger dpnId = interfaceInfo.getDpId();
long groupId = ElanUtils.getEtreeLeafLocalBCGId(etreeInstance.getEtreeLeafTagVal().getValue());
private void removeLeavesEtreeBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
WriteTransaction deleteFlowGroupTx) {
- EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
+ EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class);
if (etreeInstance != null) {
long etreeTag = etreeInstance.getEtreeLeafTagVal().getValue();
int bucketId = 0;
ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag()));
} else {
Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName)
- .setKey(new ElanKey(elanName)).build();
+ .withKey(new ElanKey(elanName)).build();
tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName),
updateElanState);
}
private DpnInterfaces removeElanDpnInterfaceFromOperationalDataStore(String elanName, BigInteger dpId,
String interfaceName, long elanTag,
WriteTransaction tx) {
- DpnInterfaces dpnInterfaces = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
- if (dpnInterfaces != null) {
- List<String> interfaceLists = dpnInterfaces.getInterfaces();
- if (interfaceLists != null) {
- interfaceLists.remove(interfaceName);
- }
+ synchronized (elanName.intern()) {
- if (interfaceLists == null || interfaceLists.isEmpty()) {
- deleteAllRemoteMacsInADpn(elanName, dpId, elanTag);
- deleteElanDpnInterface(elanName, dpId, tx);
- } else {
- dpnInterfaces = updateElanDpnInterfacesList(elanName, dpId, interfaceLists, tx);
+ DpnInterfaces dpnInterfaces = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
+ if (dpnInterfaces != null) {
+ List<String> interfaceLists = dpnInterfaces.getInterfaces();
+ if (interfaceLists != null) {
+ interfaceLists.remove(interfaceName);
+ }
+
+ if (interfaceLists == null || interfaceLists.isEmpty()) {
+ deleteAllRemoteMacsInADpn(elanName, dpId, elanTag);
+ deleteElanDpnInterface(elanName, dpId, tx);
+ } else {
+ dpnInterfaces = updateElanDpnInterfacesList(elanName, dpId, interfaceLists, tx);
+ }
}
+ return dpnInterfaces;
}
- return dpnInterfaces;
}
private void deleteAllRemoteMacsInADpn(String elanName, BigInteger dpId, long elanTag) {
e. if orig = {1,2,3,4} updated={2,3,4,5}
then 1 should be removed , 5 should be added
* */
+ @SuppressWarnings("checkstyle:ForbiddenMethod")
@Override
protected void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
// updating the static-Mac Entries for the existing elanInterface
elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(
elanName, interfaceName, staticMacEntry, tx);
}
- ElanUtils.waitForTransactionToComplete(tx);
+ ListenableFutures.addErrorLogging(ElanUtils.waitForTransactionToComplete(tx), LOG,
+ "Error in update: identifier={}, original={}, update={}", identifier, original, update);
}
}
for (String remoteIf : remoteElanInterfaces) {
ElanInterfaceMac elanIfMac = elanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf);
- if (elanIfMac == null) {
+ if (elanIfMac == null || remoteInterface == null) {
continue;
}
List<MacEntry> remoteMacEntries = elanIfMac.getMacEntry();
}
}
+ @SuppressWarnings("checkstyle:ForbiddenMethod")
List<ListenableFuture<Void>> addElanInterface(ElanInterface elanInterface,
InterfaceInfo interfaceInfo, ElanInstance elanInstance) throws ElanException {
Preconditions.checkNotNull(elanInstance, "elanInstance cannot be null");
BigInteger dpId = interfaceInfo.getDpId();
DpnInterfaces dpnInterfaces = null;
if (dpId != null && !dpId.equals(ElanConstants.INVALID_DPN)) {
- InstanceIdentifier<DpnInterfaces> elanDpnInterfaces = ElanUtils
- .getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
- Optional<DpnInterfaces> existingElanDpnInterfaces = ElanUtils.read(broker,
- LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces);
- if (!existingElanDpnInterfaces.isPresent()) {
- isFirstInterfaceInDpn = true;
- // ELAN's 1st ElanInterface added to this DPN
- dpnInterfaces = createElanInterfacesList(elanInstanceName, interfaceName, dpId, tx);
- // The 1st ElanInterface in a DPN must program the Ext Tunnel
- // table, but only if Elan has VNI
- if (isVxlanNetworkOrVxlanSegment(elanInstance)) {
- setExternalTunnelTable(dpId, elanInstance);
+ synchronized (elanInstanceName.intern()) {
+ InstanceIdentifier<DpnInterfaces> elanDpnInterfaces = ElanUtils
+ .getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
+ Optional<DpnInterfaces> existingElanDpnInterfaces = ElanUtils.read(broker,
+ LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces);
+ if (ElanUtils.isVlan(elanInstance)) {
+ isFirstInterfaceInDpn = checkIfFirstInterface(interfaceName,
+ elanInstanceName, existingElanDpnInterfaces);
+ } else {
+ isFirstInterfaceInDpn = !existingElanDpnInterfaces.isPresent();
}
- elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance, interfaceName);
- } else {
- List<String> elanInterfaces = existingElanDpnInterfaces.get().getInterfaces();
- elanInterfaces.add(interfaceName);
- if (elanInterfaces.size() == 1) { // 1st dpn interface
+ if (isFirstInterfaceInDpn) {
+ // ELAN's 1st ElanInterface added to this DPN
+ if (!existingElanDpnInterfaces.isPresent()) {
+ dpnInterfaces = createElanInterfacesList(elanInstanceName, interfaceName, dpId, tx);
+ } else {
+ List<String> elanInterfaces = existingElanDpnInterfaces.get().getInterfaces();
+ elanInterfaces.add(interfaceName);
+ dpnInterfaces = updateElanDpnInterfacesList(elanInstanceName, dpId,
+ elanInterfaces, tx);
+ }
+ // The 1st ElanInterface in a DPN must program the Ext Tunnel
+ // table, but only if Elan has VNI
+ if (isVxlanNetworkOrVxlanSegment(elanInstance)) {
+ setExternalTunnelTable(dpId, elanInstance);
+ }
elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance, interfaceName);
+ } else {
+ List<String> elanInterfaces = existingElanDpnInterfaces.get().getInterfaces();
+ elanInterfaces.add(interfaceName);
+ if (elanInterfaces.size() == 1) { // 1st dpn interface
+ elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance, interfaceName);
+ }
+ dpnInterfaces = updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces, tx);
}
- dpnInterfaces = updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces, tx);
}
}
return futures;
}
+ @SuppressWarnings("checkstyle:ForbiddenMethod")
List<ListenableFuture<Void>> setupEntriesForElanInterface(ElanInstance elanInstance,
ElanInterface elanInterface, InterfaceInfo interfaceInfo, boolean isFirstInterfaceInDpn)
throws ElanException {
}
MacEntry macEntry = new MacEntryBuilder().setMacAddress(physAddress).setInterface(interfaceName)
- .setKey(new MacEntryKey(physAddress)).build();
+ .withKey(new MacEntryKey(physAddress)).build();
elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(
elanInstanceCache.get(elanInstanceName).orNull(), interfaceInfo, macEntry);
}
+ private boolean checkIfFirstInterface(String elanInterface, String elanInstanceName,
+ Optional<DpnInterfaces> existingElanDpnInterfaces) {
+ String routerPortUuid = ElanUtils.getRouterPordIdFromElanInstance(broker, elanInstanceName);
+ if (!existingElanDpnInterfaces.isPresent()) {
+ return true;
+ }
+ if (elanInterface.equals(elanInstanceName) || elanInterface.equals(routerPortUuid)) {
+ return false;
+ }
+ DpnInterfaces dpnInterfaces = existingElanDpnInterfaces.get();
+ int dummyInterfaceCount = 0;
+ if (dpnInterfaces.getInterfaces().contains(routerPortUuid)) {
+ dummyInterfaceCount++;
+ }
+ if (dpnInterfaces.getInterfaces().contains(elanInstanceName)) {
+ dummyInterfaceCount++;
+ }
+ if (dpnInterfaces.getInterfaces().size() - dummyInterfaceCount == 0) {
+ return true;
+ }
+ return false;
+ }
+
private InstanceIdentifier<MacEntry> getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) {
return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class, new MacTableKey(elanName))
.child(MacEntry.class, new MacEntryKey(physAddress)).build();
public void removeFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
WriteTransaction deleteFlowGroupTx) {
int ifTag = interfaceInfo.getInterfaceTag();
- Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
- getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag, "group"), 9, elanInfo.getElanInstanceName(), 0,
- 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
- ElanUtils.getTunnelIdMatchForFilterEqualsLPortTag(ifTag),
- elanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
+ Flow flow = MDSALUtil.buildFlow(NwConstants.ELAN_FILTER_EQUALS_TABLE,
+ getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag, "group"));
mdsalManager.removeFlowToTx(interfaceInfo.getDpId(), flow, deleteFlowGroupTx);
int elanTag = elanInfo.getElanTag().intValue();
long groupId = ElanUtils.getElanRemoteBCGId(elanTag);
setBCGrouponOtherDpns(elanInfo, dpId, elanTag, groupId);
- EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
+ EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class);
if (etreeInstance != null) {
int etreeLeafTag = etreeInstance.getEtreeLeafTagVal().getValue().intValue();
long etreeLeafGroupId = ElanUtils.getEtreeLeafRemoteBCGId(etreeLeafTag);
}
// Install DMAC entry on dst DPN
+ @SuppressWarnings("checkstyle:ForbiddenMethod")
public List<ListenableFuture<Void>> installDMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
BigInteger dstDpId) throws ElanException {
String interfaceName = interfaceInfo.getInterfaceName();
LOG.info("Installing remote dmac for mac address {} and interface {}", macAddress, interfaceName);
synchronized (ElanUtils.getElanMacDPNKey(elanInfo.getElanTag(), macAddress,
interfaceInfo.getDpId())) {
- LOG.info("Acquired lock for mac : " + macAddress + ". Proceeding with remote dmac"
- + " install operation.");
+ LOG.info("Acquired lock for mac : {}, proceeding with remote dmac install operation", macAddress);
elanUtils.setupDMacFlowOnRemoteDpn(elanInfo, interfaceInfo, dstDpId, macAddress,
writeFlowTx);
}
private void setupLeavesLocalBroadcastGroups(ElanInstance elanInfo, DpnInterfaces newDpnInterface,
InterfaceInfo interfaceInfo) {
- EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
+ EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class);
if (etreeInstance != null) {
List<Bucket> listBucket = new ArrayList<>();
int bucketId = 0;
private void setupEtreeTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId,
WriteTransaction writeFlowGroupTx) {
- EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
+ EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class);
if (etreeInstance != null) {
setupTerminateServiceTable(elanInfo, dpId, etreeInstance.getEtreeLeafTagVal().getValue(), writeFlowGroupTx);
}
private void bindEtreeService(ElanInstance elanInfo, ElanInterface elanInterface, int lportTag,
WriteTransaction tx) {
- if (elanInterface.getAugmentation(EtreeInterface.class).getEtreeInterfaceType() == EtreeInterfaceType.Root) {
+ if (elanInterface.augmentation(EtreeInterface.class).getEtreeInterfaceType() == EtreeInterfaceType.Root) {
bindElanService(elanInfo.getElanTag(), elanInfo.getElanInstanceName(), elanInterface.getName(),
lportTag, tx);
} else {
- EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
+ EtreeInstance etreeInstance = elanInfo.augmentation(EtreeInstance.class);
if (etreeInstance == null) {
- LOG.error("EtreeInterface " + elanInterface.getName() + " is associated with a non EtreeInstance: "
- + elanInfo.getElanInstanceName());
+ LOG.error("EtreeInterface {} is associated with a non EtreeInstance: {}",
+ elanInterface.getName(), elanInfo.getElanInstanceName());
} else {
bindElanService(etreeInstance.getEtreeLeafTagVal().getValue(), elanInfo.getElanInstanceName(),
elanInterface.getName(), lportTag, tx);
}
private boolean isStandardElanService(ElanInterface elanInterface) {
- return elanInterface.getAugmentation(EtreeInterface.class) == null;
+ return elanInterface.augmentation(EtreeInterface.class) == null;
}
protected void unbindService(String interfaceName, ReadWriteTransaction tx) throws ReadFailedException {
private DpnInterfaces updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId,
List<String> interfaceNames, WriteTransaction tx) {
DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId).setInterfaces(interfaceNames)
- .setKey(new DpnInterfacesKey(dpId)).build();
+ .withKey(new DpnInterfacesKey(dpId)).build();
tx.put(LogicalDatastoreType.OPERATIONAL,
ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface,
WriteTransaction.CREATE_MISSING_PARENTS);
List<String> interfaceNames = new ArrayList<>();
interfaceNames.add(interfaceName);
DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId).setInterfaces(interfaceNames)
- .setKey(new DpnInterfacesKey(dpId)).build();
+ .withKey(new DpnInterfacesKey(dpId)).build();
tx.put(LogicalDatastoreType.OPERATIONAL,
ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), dpnInterface,
WriteTransaction.CREATE_MISSING_PARENTS);
// Static-Mac Entries..
if (!interfaceMacTables.isPresent()) {
ElanInterfaceMac elanInterfaceMacTable = new ElanInterfaceMacBuilder().setElanInterface(interfaceName)
- .setKey(new ElanInterfaceMacKey(interfaceName)).build();
+ .withKey(new ElanInterfaceMacKey(interfaceName)).build();
tx.put(LogicalDatastoreType.OPERATIONAL,
ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName), elanInterfaceMacTable,
WriteTransaction.CREATE_MISSING_PARENTS);
}
interfaceLists.add(interfaceName);
Elan elanState = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(interfaceLists)
- .setKey(new ElanKey(elanInstanceName)).build();
+ .withKey(new ElanKey(elanInstanceName)).build();
tx.put(LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName),
elanState, WriteTransaction.CREATE_MISSING_PARENTS);
}
+ "skipping this ELAN for tunnel handling", elanName);
continue;
}
- if (ElanUtils.isFlat(elanInfo) || ElanUtils.isVlan(elanInfo)) {
+ if (!isVxlanNetworkOrVxlanSegment(elanInfo)) {
LOG.debug("Ignoring internal tunnel state event for Flat/Vlan elan {}", elanName);
continue;
}