import java.util.List;
import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.genius.infra.Datastore.Configuration;
import org.opendaylight.genius.infra.TypedWriteTransaction;
boolean isVpnFirstEndPoint,
VrfEntry vrfEntry);
+ boolean checkFibEntryExist(DataBroker broker, String rd, String prefix, String nextHopIp);
+
void programDcGwLoadBalancingGroup(Uint64 dpnId,
String destinationIp, int addRemoveOrUpdate, boolean isTunnelUp,
Class<? extends TunnelTypeBase> tunnelType);
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Singleton;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.genius.infra.Datastore.Configuration;
import org.opendaylight.genius.infra.TypedWriteTransaction;
vrfEntryListener.removeInterVPNLinkRouteFlows(interVpnLink, vpnName, vrfEntry);
}
+ @Override
+ public boolean checkFibEntryExist(DataBroker broker, String rd, String prefix, String nextHopIp) {
+ return fibUtil.checkFibEntryExist(broker, rd, prefix, nextHopIp);
+ }
+
@Override
public void programDcGwLoadBalancingGroup(Uint64 dpnId, String destinationIp,
int addRemoveOrUpdate, boolean isTunnelUp,
}
return false;
}
+
+ public static boolean checkFibEntryExist(DataBroker broker, String rd, String prefix, String nextHopIp) {
+ InstanceIdentifier<VrfEntry> vrfEntryId =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
+ .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
+ Optional<VrfEntry> entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+ if (entry.isPresent()) {
+ List<RoutePaths> paths = entry.get().getRoutePaths();
+ for (RoutePaths path: paths) {
+ if (path.getNexthopAddress().equals(nextHopIp)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
}
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
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.interfaces.rev140508.interfaces.state.Interface.OperStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+ " triggered by northbound agent. ignoring.", ifName, vpnName);
continue;
}
+ handleMipAdjRemoval(cfgVpnInterface, vpnName);
final VpnInterfaceOpDataEntry vpnInterface = optVpnInterface.get();
String gwMac = intrf.getPhysAddress() != null ? intrf.getPhysAddress()
.getValue() : vpnInterface.getGatewayMacAddress();
if (optVpnInterface.isPresent()) {
VpnInterfaceOpDataEntry vpnOpInterface =
optVpnInterface.get();
+ handleMipAdjRemoval(vpnIf, vpnName);
vpnInterfaceManager.processVpnInterfaceDown(dpnId,
vpnIf.getName(), ifIndex, update.getPhysAddress()
.getValue(), vpnOpInterface, true,
}
}
+ private void handleMipAdjRemoval(VpnInterface cfgVpnInterface, String vpnName) {
+ String interfaceName = cfgVpnInterface.getName();
+ Adjacencies adjacencies = cfgVpnInterface.augmentation(Adjacencies.class);
+ if (adjacencies != null) {
+ List<Adjacency> adjacencyList = adjacencies.getAdjacency();
+ if (!adjacencyList.isEmpty()) {
+ for (Adjacency adj : adjacencyList) {
+ if (adj.getAdjacencyType() != Adjacency.AdjacencyType.PrimaryAdjacency) {
+ String ipAddress = adj.getIpAddress();
+ String prefix = ipAddress.split("/")[0];
+ LearntVpnVipToPort vpnVipToPort = vpnUtil.getLearntVpnVipToPort(vpnName, prefix);
+ if (vpnVipToPort != null && vpnVipToPort.getPortName().equals(interfaceName)) {
+ vpnUtil.removeMipAdjacency(vpnName, interfaceName, ipAddress, null);
+ } else {
+ LOG.debug("IP {} could be extra-route or learnt-ip on different interface"
+ + "than oper-vpn-interface {}", ipAddress, interfaceName);
+ }
+ }
+ }
+ }
+ }
+ }
+
private class PostVpnInterfaceThreadWorker implements FutureCallback<Void> {
private final String interfaceName;
private final boolean add;
}
String prefix = null;
List<Adjacency> value = new ArrayList<>();
- boolean isNextHopAddReqd = false;
+ boolean isFibNextHopAddReqd = false;
String vpnName = vpnInterface.getVpnInstanceName();
Uint32 vpnId = vpnUtil.getVpnId(vpnName);
String primaryRd = vpnUtil.getPrimaryRd(vpnName);
List<String> nextHopList = adj.getNextHopIpList();
// If TEP is added , update the nexthop of primary adjacency.
// Secondary adj nexthop is already pointing to primary adj IP address.
- if (nextHopList == null || nextHopList.isEmpty()) {
- isNextHopAddReqd = true;
- }
-
if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
value.add(new AdjacencyBuilder(adj).setNextHopIpList(nhList).build());
+ if (nextHopList != null && !nextHopList.isEmpty()) {
+ /* everything right already */
+ } else {
+ isFibNextHopAddReqd = true;
+ }
} else {
Optional<VrfEntry> vrfEntryOptional = FibHelper.getVrfEntry(dataBroker, primaryRd, prefix);
if (!vrfEntryOptional.isPresent()) {
nhList = FibHelper.getNextHopListFromRoutePaths(vrfEntryOptional.get());
if (!nhList.contains(srcTepIp)) {
nhList.add(srcTepIp);
- isNextHopAddReqd = true;
+ isFibNextHopAddReqd = true;
}
value.add(adj);
}
- if (isNextHopAddReqd) {
+ if (isFibNextHopAddReqd) {
updateLabelMapper(label, nhList);
LOG.info("updateVpnInterfaceOnTepAdd: Updated label mapper : label {} dpn {} prefix {} nexthoplist {}"
+ " vpn {} vpnid {} rd {} interface {}", label, srcDpnId , prefix, nhList,
Optional<VpnInterfaceOpDataEntry> vpnInterfaceOpDataEnteryOptional =
SingleTransactionDataBroker.syncReadOptional(dataBroker,
LogicalDatastoreType.OPERATIONAL, identifier);
- boolean isLearntIP = Boolean.FALSE;
+ boolean isNonPrimaryAdjIp = false;
String primaryRd = vpnUtil.getVpnRd(vpnName);
LOG.info("removeAdjacenciesFromVpn: For interface {} on dpn {} RD recovered for vpn {} as rd {}",
interfaceName, dpnId, vpnName, primaryRd);
List<String> nhList;
if (nextHop.getAdjacencyType() != AdjacencyType.PrimaryAdjacency) {
nhList = getNextHopForNonPrimaryAdjacency(nextHop, vpnName, dpnId, interfaceName);
- isLearntIP = nextHop.getAdjacencyType() == AdjacencyType.LearntIp ? true : false;
+ isNonPrimaryAdjIp = Boolean.TRUE;
} else {
// This is a primary adjacency
nhList = nextHop.getNextHopIpList() != null ? nextHop.getNextHopIpList()
removeGwMacAndArpResponderFlows(nextHop, vpnId, dpnId, lportTag, gwMac,
vpnInterfaceOpDataEnteryOptional.get().getGatewayIpAddress(),
interfaceName, writeInvTxn);
+ isNonPrimaryAdjIp = Boolean.FALSE;
}
if (!nhList.isEmpty()) {
if (Objects.equals(primaryRd, vpnName)) {
interfaceName, dpnId, writeConfigTxn, writeOperTxn));
} else {
removeAdjacencyFromBgpvpn(nextHop, nhList, vpnName, primaryRd, dpnId, rd,
- interfaceName, writeConfigTxn, writeOperTxn);
+ interfaceName, isNonPrimaryAdjIp, writeConfigTxn, writeOperTxn);
}
} else {
LOG.error("removeAdjacenciesFromVpn: nextHop empty for ip {} rd {} adjacencyType {}"
vpnVipToPort.getPortName(), ip, dpnId, vpnName);
}
// Remove the MIP-IP from VpnPortIpToPort.
- if (isLearntIP) {
+ if (isNonPrimaryAdjIp) {
VpnPortipToPort persistedIp = vpnUtil.getVpnPortipToPort(vpnName, ip);
if (persistedIp != null && persistedIp.isLearntIp()
&& persistedIp.getPortName().equals(interfaceName)) {
}
private void removeAdjacencyFromBgpvpn(Adjacency nextHop, List<String> nhList, String vpnName, String primaryRd,
- Uint64 dpnId, String rd, String interfaceName,
+ Uint64 dpnId, String rd, String interfaceName, boolean isNonPrimaryAdjIp,
TypedWriteTransaction<Configuration> writeConfigTxn,
TypedWriteTransaction<Operational> writeOperTx) {
List<VpnInstanceOpDataEntry> vpnsToImportRoute =
vpnUtil.getVpnsImportingMyRoute(vpnName);
nhList.forEach((nh) -> {
//IRT: remove routes from other vpns importing it
- vpnManager.removePrefixFromBGP(vpnName, primaryRd, rd, interfaceName, nextHop.getIpAddress(),
- nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn, writeOperTx);
+ if (isNonPrimaryAdjIp) {
+ removeLearntPrefixFromBGP(rd, nextHop.getIpAddress(), nh, writeConfigTxn);
+ } else {
+ vpnManager.removePrefixFromBGP(vpnName, primaryRd, rd, interfaceName, nextHop.getIpAddress(),
+ nextHop.getNextHopIpList().get(0), nh, dpnId, writeConfigTxn, writeOperTx);
+ }
for (VpnInstanceOpDataEntry vpn : vpnsToImportRoute) {
String vpnRd = vpn.getVrfId();
if (vpnRd != null) {
});
}
+ @SuppressWarnings("checkstyle:IllegalCatch")
+ private void removeLearntPrefixFromBGP(String rd, String prefix, String nextHop,
+ TypedWriteTransaction<Configuration> writeConfigTxn) {
+ try {
+ if (!fibManager.checkFibEntryExist(dataBroker, rd, prefix, nextHop)) {
+ LOG.info("removeLearntPrefixFromBGP: IP {} with nexthop {} rd {} is already removed.Ignoring this"
+ + " operation", prefix, nextHop, rd);
+ return;
+ }
+ LOG.info("removeLearntPrefixFromBGP: VPN WITHDRAW: Removing Fib Entry rd {} prefix {} nexthop {}",
+ rd, prefix, nextHop);
+ fibManager.removeOrUpdateFibEntry(rd, prefix, nextHop, writeConfigTxn);
+ bgpManager.withdrawPrefix(rd, prefix); // TODO: Might be needed to include nextHop here
+ LOG.info("removeLearntPrefixFromBGP: VPN WITHDRAW: Removed Fib Entry rd {} prefix {} nexthop {}",
+ rd, prefix, nextHop);
+ } catch (Exception e) {
+ LOG.error("removeLearntPrefixFromBGP: Delete prefix {} rd {} nextHop {} failed", prefix, rd, nextHop, e);
+ }
+ }
+
private void removeGwMacAndArpResponderFlows(Adjacency nextHop, Uint32 vpnId, Uint64 dpnId,
int lportTag, String gwMac, String gwIp, String interfaceName,
TypedReadWriteTransaction<Configuration> writeInvTxn)
new LearntVpnVipToPortKey(fixedIp, vpnName)).build();
}
- void removeLearntVpnVipToPort(String vpnName, String fixedIp,
- @Nullable TypedWriteTransaction<Operational> writeOperTxn) {
+ public void removeLearntVpnVipToPort(String vpnName, String fixedIp,
+ @Nullable TypedWriteTransaction<Operational> writeOperTxn) {
final InstanceIdentifier<LearntVpnVipToPort> id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp);
final ReentrantLock lock = lockFor(vpnName, fixedIp);
lock.lock();
}
}
- protected static void removeVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp,
+ public static void removeVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp,
@Nullable TypedWriteTransaction<Configuration> writeConfigTxn) {
final InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
final ReentrantLock lock = lockFor(vpnName, fixedIp);
VpnUtil.removeVpnPortFixedIpToPort(dataBroker, vpnName, prefix, null);
}
+ public void removeMipAdjacency(String vpnName, String vpnInterface, String prefix,
+ TypedWriteTransaction<Configuration> writeConfigTxn) {
+ String ip = VpnUtil.getIpPrefix(prefix);
+ LOG.trace("Removing {} adjacency from Old VPN Interface {} ", ip, vpnInterface);
+ InstanceIdentifier<VpnInterface> vpnIfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface);
+ InstanceIdentifier<Adjacencies> path = vpnIfId.augmentation(Adjacencies.class);
+ //TODO: Remove synchronized?
+
+ Optional<Adjacencies> adjacencies = read(LogicalDatastoreType.OPERATIONAL, path);
+ if (adjacencies.isPresent()) {
+ InstanceIdentifier<Adjacency> adjacencyIdentifier = getAdjacencyIdentifier(vpnInterface, prefix);
+ writeConfigTxn.delete(adjacencyIdentifier);
+ LOG.error("removeMipAdjacency: Successfully Deleted Adjacency {} from interface {} vpn {}", ip,
+ vpnInterface, vpnName);
+ }
+ }
+
public void removeMipAdjacency(String vpnInterface, String ipAddress) {
String prefix = VpnUtil.getIpPrefix(ipAddress);
InstanceIdentifier<Adjacency> adjacencyIdentifier = getAdjacencyIdentifier(vpnInterface, prefix);
try {
- SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
+ SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+ adjacencyIdentifier);
} catch (TransactionCommitFailedException e) {
if (e.getCause() instanceof ModifiedNodeDoesNotExistException) {
LOG.debug("vpnInterface {} is already deleted. prefix={}", vpnInterface, prefix);
if (vpnVipToPort != null && macEntry.getCreatedTime().equals(vpnVipToPort.getCreationTime())) {
String jobKey = VpnUtil.buildIpMonitorJobKey(macEntry.getIpAddress().getHostAddress(),
macEntry.getVpnName());
- jobCoordinator.enqueueJob(jobKey, new IpMonitorStopTask(macEntry, Boolean.TRUE, vpnUtil,
+ jobCoordinator.enqueueJob(jobKey, new IpMonitorStopTask(macEntry, dataBroker, Boolean.TRUE, vpnUtil,
alivenessMonitorUtils));
}
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.infra.Datastore;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
+import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
import org.opendaylight.netvirt.vpnmanager.VpnUtil;
import org.opendaylight.netvirt.vpnmanager.iplearn.model.MacEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
public class IpMonitorStopTask implements Callable<List<ListenableFuture<Void>>> {
private static final Logger LOG = LoggerFactory.getLogger(IpMonitorStopTask.class);
private MacEntry macEntry;
+ private DataBroker dataBroker;
private final AlivenessMonitorUtils alivenessMonitorUtils;
private boolean isRemoveMipAdjAndLearntIp;
private final VpnUtil vpnUtil;
+ private final ManagedNewTransactionRunner txRunner;
- public IpMonitorStopTask(MacEntry macEntry, boolean removeMipAdjAndLearntIp, VpnUtil vpnUtil,
- AlivenessMonitorUtils alivenessMonitorUtils) {
+ public IpMonitorStopTask(MacEntry macEntry, DataBroker dataBroker, boolean removeMipAdjAndLearntIp, VpnUtil vpnUtil,
+ AlivenessMonitorUtils alivenessMonitorUtils) {
this.macEntry = macEntry;
+ this.dataBroker = dataBroker;
this.alivenessMonitorUtils = alivenessMonitorUtils;
this.isRemoveMipAdjAndLearntIp = removeMipAdjAndLearntIp;
this.vpnUtil = vpnUtil;
+ this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
}
@Override
+ "Ignoring this remove event.", learntIp, vpnName);
return futures;
}
- vpnUtil.removeMipAdjAndLearntIp(vpnName, macEntry.getInterfaceName(), learntIp);
+ vpnUtil.removeLearntVpnVipToPort(macEntry.getVpnName(),
+ macEntry.getIpAddress().getHostAddress(), null);
+ vpnUtil.removeVpnPortFixedIpToPort(dataBroker, macEntry.getVpnName(),
+ macEntry.getIpAddress().getHostAddress(), null);
+
+ ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+ Datastore.CONFIGURATION, tx -> vpnUtil.removeMipAdjacency(macEntry.getVpnName(),
+ macEntry.getInterfaceName(), macEntry.getIpAddress().getHostAddress(), tx)),
+ LOG, "ArpMonitorStopTask: Error writing to datastore for Vpn {} IP {}",
+ macEntry.getVpnName(), macEntry.getIpAddress().getHostAddress());
} else {
// Delete only MIP adjacency
vpnUtil.removeMipAdjacency(macEntry.getInterfaceName(), learntIp);
}
return futures;
}
-
-
}
return;
}
String vpnName = value.getVpnName();
+ String learntIp = srcInetAddr.getHostAddress();
+ LearntVpnVipToPort vpnVipToPort = vpnUtil.getLearntVpnVipToPort(vpnName, learntIp);
+ if (vpnVipToPort != null && !vpnVipToPort.getCreationTime().equals(value.getCreationTime())) {
+ LOG.warn("The MIP {} over vpn {} has been learnt again and processed. "
+ + "Ignoring this remove event.", learntIp, vpnName);
+ return;
+ }
MacAddress srcMacAddress = MacAddress.getDefaultInstance(value.getMacAddress());
String interfaceName = value.getPortName();
MacEntry macEntry = new MacEntry(vpnName, srcMacAddress, srcInetAddr, interfaceName,
value.getCreationTime());
jobCoordinator.enqueueJob(VpnUtil.buildIpMonitorJobKey(srcInetAddr.toString(), vpnName),
- new IpMonitorStopTask(macEntry, Boolean.FALSE, vpnUtil, alivenessMonitorUtils));
+ new IpMonitorStopTask(macEntry, dataBroker, Boolean.FALSE, vpnUtil, alivenessMonitorUtils));
} catch (UnknownHostException e) {
LOG.error("Error in deserializing packet {} with exception", value, e);
}