use of org.opendaylight.controller.md.sal.binding.api.WriteTransaction in project netvirt by opendaylight.
the class ElanInterfaceManager method addElanInterface.
List<ListenableFuture<Void>> addElanInterface(ElanInterface elanInterface, InterfaceInfo interfaceInfo, ElanInstance elanInstance) throws ElanException {
Preconditions.checkNotNull(elanInstance, "elanInstance cannot be null");
Preconditions.checkNotNull(interfaceInfo, "interfaceInfo cannot be null");
Preconditions.checkNotNull(elanInterface, "elanInterface cannot be null");
String interfaceName = elanInterface.getName();
String elanInstanceName = elanInterface.getElanInstanceName();
Elan elanInfo = ElanUtils.getElanByName(broker, elanInstanceName);
WriteTransaction tx = broker.newWriteOnlyTransaction();
if (elanInfo == null) {
List<String> elanInterfaces = new ArrayList<>();
elanInterfaces.add(interfaceName);
ElanUtils.updateOperationalDataStore(idManager, elanInstance, elanInterfaces, tx);
} else {
createElanStateList(elanInstanceName, interfaceName, tx);
}
boolean isFirstInterfaceInDpn = false;
// Specific actions to the DPN where the ElanInterface has been added,
// for example, programming the
// External tunnel table if needed or adding the ElanInterface to the
// DpnInterfaces in the operational DS.
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);
// 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);
}
}
// add code to install Local/Remote BC group, unknow DMAC entry,
// terminating service table flow entry
// call bindservice of interfacemanager to create ingress table flow
// enty.
// Add interface to the ElanInterfaceForwardingEntires Container
createElanInterfaceTablesList(interfaceName, tx);
List<ListenableFuture<Void>> futures = new ArrayList<>();
futures.add(ElanUtils.waitForTransactionToComplete(tx));
installEntriesForFirstInterfaceonDpn(elanInstance, interfaceInfo, dpnInterfaces, isFirstInterfaceInDpn);
// for internal vlan networks
if (ElanUtils.isVlan(elanInstance) && !elanInstance.isExternal()) {
if (interfaceManager.isExternalInterface(interfaceName)) {
LOG.debug("adding vlan prv intf {} to elan {} BC group", interfaceName, elanInstanceName);
handleExternalInterfaceEvent(elanInstance, dpnInterfaces, dpId);
}
}
if (isFirstInterfaceInDpn && isVxlanNetworkOrVxlanSegment(elanInstance)) {
// update the remote-DPNs remoteBC group entry with Tunnels
LOG.trace("update remote bc group for elan {} on other DPNs for newly added dpn {}", elanInstance, dpId);
setElanAndEtreeBCGrouponOtherDpns(elanInstance, dpId);
}
String jobKey = ElanUtils.getElanInterfaceJobKey(interfaceName);
InterfaceAddWorkerOnElanInterface addWorker = new InterfaceAddWorkerOnElanInterface(jobKey, elanInterface, interfaceInfo, elanInstance, isFirstInterfaceInDpn, this);
jobCoordinator.enqueueJob(jobKey, addWorker, ElanConstants.JOB_MAX_RETRIES);
return futures;
}
use of org.opendaylight.controller.md.sal.binding.api.WriteTransaction in project netvirt by opendaylight.
the class ElanInterfaceManager method setupEntriesForElanInterface.
List<ListenableFuture<Void>> setupEntriesForElanInterface(ElanInstance elanInstance, ElanInterface elanInterface, InterfaceInfo interfaceInfo, boolean isFirstInterfaceInDpn) throws ElanException {
String elanInstanceName = elanInstance.getElanInstanceName();
String interfaceName = elanInterface.getName();
WriteTransaction tx = broker.newWriteOnlyTransaction();
BigInteger dpId = interfaceInfo.getDpId();
WriteTransaction writeFlowGroupTx = broker.newWriteOnlyTransaction();
installEntriesForElanInterface(elanInstance, elanInterface, interfaceInfo, isFirstInterfaceInDpn, tx, writeFlowGroupTx);
List<StaticMacEntries> staticMacEntriesList = elanInterface.getStaticMacEntries();
List<PhysAddress> staticMacAddresses = Lists.newArrayList();
boolean isInterfaceOperational = isOperational(interfaceInfo);
if (ElanUtils.isNotEmpty(staticMacEntriesList)) {
for (StaticMacEntries staticMacEntry : staticMacEntriesList) {
InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, staticMacEntry.getMacAddress());
Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId);
if (existingMacEntry.isPresent()) {
elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(elanInstanceName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get(), tx);
} else {
elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(elanInstanceName, interfaceName, staticMacEntry, tx);
}
if (isInterfaceOperational) {
// Setting SMAC, DMAC, UDMAC in this DPN and also in other
// DPNs
String macAddress = staticMacEntry.getMacAddress().getValue();
LOG.info("programming smac and dmacs for {} on source and other DPNs for elan {} and interface {}", macAddress, elanInstanceName, interfaceName);
elanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, staticMacEntry.getMacAddress().getValue(), true, writeFlowGroupTx);
}
}
if (isInterfaceOperational) {
// on purpose.
for (StaticMacEntries staticMacEntry : staticMacEntriesList) {
staticMacAddresses.add(staticMacEntry.getMacAddress());
}
elanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(), dpId, staticMacAddresses);
}
}
List<ListenableFuture<Void>> futures = new ArrayList<>();
futures.add(ElanUtils.waitForTransactionToComplete(tx));
futures.add(ElanUtils.waitForTransactionToComplete(writeFlowGroupTx));
if (isInterfaceOperational && !interfaceManager.isExternalInterface(interfaceName)) {
// At this point, the interface is operational and D/SMAC flows have been configured, mark the port active
try {
Port neutronPort = neutronVpnManager.getNeutronPort(interfaceName);
if (neutronPort != null) {
NeutronUtils.updatePortStatus(interfaceName, NeutronUtils.PORT_STATUS_ACTIVE, broker);
}
} catch (IllegalArgumentException ex) {
LOG.trace("Interface: {} is not part of Neutron Network", interfaceName);
}
}
return futures;
}
use of org.opendaylight.controller.md.sal.binding.api.WriteTransaction in project netvirt by opendaylight.
the class ElanInterfaceManager method removeElanInterface.
public List<ListenableFuture<Void>> removeElanInterface(ElanInstance elanInfo, String interfaceName, InterfaceInfo interfaceInfo) {
String elanName = elanInfo.getElanInstanceName();
boolean isLastElanInterface = false;
boolean isLastInterfaceOnDpn = false;
BigInteger dpId = null;
long elanTag = elanInfo.getElanTag();
// We use two transaction so we don't suffer on multiple shards (interfaces and flows)
WriteTransaction interfaceTx = broker.newWriteOnlyTransaction();
Elan elanState = removeElanStateForInterface(elanInfo, interfaceName, interfaceTx);
if (elanState == null) {
interfaceTx.cancel();
return Collections.emptyList();
}
WriteTransaction flowTx = broker.newWriteOnlyTransaction();
List<String> elanInterfaces = elanState.getElanInterfaces();
if (elanInterfaces.isEmpty()) {
isLastElanInterface = true;
}
if (interfaceInfo != null) {
dpId = interfaceInfo.getDpId();
DpnInterfaces dpnInterfaces = removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName, elanTag, interfaceTx);
/*
* If there are not elan ports, remove the unknown dmac, terminating
* service table flows, remote/local bc group
*/
if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null || dpnInterfaces.getInterfaces().isEmpty()) {
// No more Elan Interfaces in this DPN
LOG.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId);
if (!elanUtils.isOpenstackVniSemanticsEnforced()) {
removeDefaultTermFlow(dpId, elanInfo.getElanTag());
}
removeUnknownDmacFlow(dpId, elanInfo, flowTx, elanInfo.getElanTag());
removeEtreeUnknownDmacFlow(dpId, elanInfo, flowTx);
removeElanBroadcastGroup(elanInfo, interfaceInfo, flowTx);
removeLocalBroadcastGroup(elanInfo, interfaceInfo, flowTx);
removeEtreeBroadcastGrups(elanInfo, interfaceInfo, flowTx);
if (isVxlanNetworkOrVxlanSegment(elanInfo)) {
if (elanUtils.isOpenstackVniSemanticsEnforced()) {
elanUtils.removeTerminatingServiceAction(dpId, elanUtils.getVxlanSegmentationId(elanInfo).intValue());
}
unsetExternalTunnelTable(dpId, elanInfo);
}
isLastInterfaceOnDpn = true;
} else {
setupLocalBroadcastGroups(elanInfo, dpnInterfaces, interfaceInfo);
}
}
List<ListenableFuture<Void>> futures = new ArrayList<>();
futures.add(ElanUtils.waitForTransactionToComplete(interfaceTx));
futures.add(ElanUtils.waitForTransactionToComplete(flowTx));
if (isLastInterfaceOnDpn && dpId != null && isVxlanNetworkOrVxlanSegment(elanInfo)) {
setElanAndEtreeBCGrouponOtherDpns(elanInfo, dpId);
}
InterfaceRemoveWorkerOnElanInterface removeInterfaceWorker = new InterfaceRemoveWorkerOnElanInterface(interfaceName, elanInfo, interfaceInfo, this, isLastElanInterface);
jobCoordinator.enqueueJob(ElanUtils.getElanInterfaceJobKey(interfaceName), removeInterfaceWorker, ElanConstants.JOB_MAX_RETRIES);
return futures;
}
use of org.opendaylight.controller.md.sal.binding.api.WriteTransaction in project netvirt by opendaylight.
the class ElanInterfaceManager method update.
/*
* Possible Scenarios for update
* a. if orig={1,2,3,4} and updated=null or updated={}
then all {1,2,3,4} should be removed
b. if orig=null or orig={} and updated ={1,2,3,4}
then all {1,2,3,4} should be added
c. if orig = {1,2,3,4} updated={2,3,4}
then 1 should be removed
d. basically if orig = { 1,2,3,4} and updated is {1,2,3,4,5}
then we should just add 5
e. if orig = {1,2,3,4} updated={2,3,4,5}
then 1 should be removed , 5 should be added
* */
@Override
protected void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
// updating the static-Mac Entries for the existing elanInterface
String elanName = update.getElanInstanceName();
String interfaceName = update.getName();
List<StaticMacEntries> originalStaticMacEntries = original.getStaticMacEntries();
List<StaticMacEntries> updatedStaticMacEntries = update.getStaticMacEntries();
List<StaticMacEntries> deletedEntries = ElanUtils.diffOf(originalStaticMacEntries, updatedStaticMacEntries);
List<StaticMacEntries> updatedEntries = ElanUtils.diffOf(updatedStaticMacEntries, originalStaticMacEntries);
deletedEntries.forEach((deletedEntry) -> removeInterfaceStaticMacEntries(elanName, interfaceName, deletedEntry.getMacAddress()));
/*if updatedStaticMacEntries is NOT NULL, which means as part of update call these entries were added.
* Hence add the macentries for the same.*/
for (StaticMacEntries staticMacEntry : updatedEntries) {
InstanceIdentifier<MacEntry> macEntryIdentifier = getMacEntryOperationalDataPath(elanName, staticMacEntry.getMacAddress());
Optional<MacEntry> existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macEntryIdentifier);
WriteTransaction tx = broker.newWriteOnlyTransaction();
if (existingMacEntry.isPresent()) {
elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(elanName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get(), tx);
} else {
elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(elanName, interfaceName, staticMacEntry, tx);
}
ElanUtils.waitForTransactionToComplete(tx);
}
}
use of org.opendaylight.controller.md.sal.binding.api.WriteTransaction in project netvirt by opendaylight.
the class VpnInterfaceManager method handleVpnsExportingRoutes.
// TODO Clean up the exception handling
@SuppressWarnings("checkstyle:IllegalCatch")
void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
List<VpnInstanceOpDataEntry> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
for (VpnInstanceOpDataEntry vpn : vpnsToExportRoute) {
List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(dataBroker, vpn.getVrfId());
WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
if (vrfEntries != null) {
for (VrfEntry vrfEntry : vrfEntries) {
try {
if (!FibHelper.isControllerManagedNonInterVpnLinkRoute(RouteOrigin.value(vrfEntry.getOrigin()))) {
LOG.info("handleVpnsExportingRoutes: vrfEntry with rd {} prefix {}" + " is not a controller managed non intervpn link route. Ignoring.", vpn.getVrfId(), vrfEntry.getDestPrefix());
continue;
}
String prefix = vrfEntry.getDestPrefix();
String gwMac = vrfEntry.getGatewayMacAddress();
vrfEntry.getRoutePaths().forEach(routePath -> {
String nh = routePath.getNexthopAddress();
int label = routePath.getLabel().intValue();
if (FibHelper.isControllerManagedVpnInterfaceRoute(RouteOrigin.value(vrfEntry.getOrigin()))) {
LOG.info("handleVpnsExportingRoutesImporting: Importing fib entry rd {} prefix {}" + " nexthop {} label {} to vpn {} vpnRd {}", vpn.getVrfId(), prefix, nh, label, vpnName, vpnRd);
fibManager.addOrUpdateFibEntry(vpnRd, null, /*macAddress*/
prefix, Collections.singletonList(nh), VrfEntry.EncapType.Mplsgre, label, 0, /*l3vni*/
gwMac, null, /*parentVpnRd*/
RouteOrigin.SELF_IMPORTED, writeConfigTxn);
} else {
LOG.info("handleVpnsExportingRoutes: Importing subnet route fib entry rd {} prefix {}" + " nexthop {} label {} to vpn {} vpnRd {}", vpn.getVrfId(), prefix, nh, label, vpnName, vpnRd);
SubnetRoute route = vrfEntry.getAugmentation(SubnetRoute.class);
importSubnetRouteForNewVpn(vpnRd, prefix, nh, label, route, writeConfigTxn);
}
});
} catch (RuntimeException e) {
LOG.error("getNextHopAddressList: Exception occurred while importing route with rd {}" + " prefix {} routePaths {} to vpn {} vpnRd {}", vpn.getVrfId(), vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), vpnName, vpnRd);
}
}
writeConfigTxn.submit();
} else {
LOG.info("getNextHopAddressList: No vrf entries to import from vpn {} with rd {} to vpn {} with rd {}", vpn.getVpnInstanceName(), vpn.getVrfId(), vpnName, vpnRd);
}
}
}
Aggregations