<artifactId>bgpmanager-api</artifactId>
<version>${vpnservices.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.genius</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${genius.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>model-bgp</artifactId>
initer.countDown();
bgpConfigurationManager = this;
+ BgpUtil.batchSize = BgpUtil.BATCH_SIZE;
+ if (Integer.getInteger("batch.size") != null) {
+ BgpUtil.batchSize = Integer.getInteger("batch.size");
+ }
+ BgpUtil.batchInterval = BgpUtil.PERIODICITY;
+ if (Integer.getInteger("batch.wait.time") != null) {
+ BgpUtil.batchInterval = Integer.getInteger("batch.wait.time");
+ }
+ BgpUtil.registerWithBatchManager(new BgpVrfBatchHandler());
}
boolean ignoreClusterDcnEventForFollower() {
protected synchronized void
add(InstanceIdentifier<AsId> iid, AsId val) {
- LOG.error("received bgp add asid");
+ LOG.error("received bgp add asid {}",val);
if (ignoreClusterDcnEventForFollower()) {
return;
}
import org.opendaylight.controller.md.sal.binding.api.*;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.*;
+import org.opendaylight.genius.utils.batching.ActionableResource;
+import org.opendaylight.genius.utils.batching.ActionableResourceImpl;
+import org.opendaylight.genius.utils.batching.ResourceBatchingManager;
+import org.opendaylight.genius.utils.batching.ResourceHandler;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
private static final Logger LOG = LoggerFactory.getLogger(BgpUtil.class);
private static DataBroker dataBroker;
private static BindingTransactionChain fibTransact;
+ public static final int PERIODICITY = 500;
private static AtomicInteger pendingWrTransaction = new AtomicInteger(0);
+ public static final int BATCH_SIZE = 1000;
+ public static Integer batchSize;
+ public static Integer batchInterval;
private static int txChainAttempts = 0;
+ private static BlockingQueue<ActionableResource> bgpRoutesBufferQ = new LinkedBlockingQueue<>();
+
// return number of pending Write Transactions with BGP-Util (no read)
public static int getGetPendingWrTransaction() {
return pendingWrTransaction.get();
return fibTransact;
}
+ static void registerWithBatchManager(ResourceHandler resourceHandler) {
+ ResourceBatchingManager resBatchingManager = ResourceBatchingManager.getInstance();
+ resBatchingManager.registerBatchableResource("BGP-VRFENTRY", bgpRoutesBufferQ, resourceHandler);
+ }
+
static <T extends DataObject> void update(DataBroker broker, final LogicalDatastoreType datastoreType,
final InstanceIdentifier<T> path, final T data) {
- threadPool.submit(new MdsalDsTask<>(datastoreType, path, data, TransactionType.UPDATE));
+ ActionableResource actResource = new ActionableResourceImpl(path.toString());
+ actResource.setAction(ActionableResource.UPDATE);
+ actResource.setInstanceIdentifier(path);
+ actResource.setInstance(data);
+ bgpRoutesBufferQ.add(actResource);
}
-
public static <T extends DataObject> void write(DataBroker broker, final LogicalDatastoreType datastoreType,
final InstanceIdentifier<T> path, final T data) {
- threadPool.submit(new MdsalDsTask<>(datastoreType, path, data, TransactionType.WRITE));
+ ActionableResource actResource = new ActionableResourceImpl(path.toString());
+ actResource.setAction(ActionableResource.CREATE);
+ actResource.setInstanceIdentifier(path);
+ actResource.setInstance(data);
+ bgpRoutesBufferQ.add(actResource);
}
static <T extends DataObject> void delete(DataBroker broker, final LogicalDatastoreType datastoreType,
final InstanceIdentifier<T> path) {
- threadPool.submit(new MdsalDsTask<>(datastoreType, path, null, TransactionType.DELETE));
- }
-
- static enum TransactionType {
- WRITE, UPDATE, DELETE;
- }
-
- static class MdsalDsTask<T extends DataObject> implements Runnable {
- LogicalDatastoreType datastoreType;
- InstanceIdentifier<T> path;
- T data;
- TransactionType type;
-
- public MdsalDsTask(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path, T data, TransactionType type) {
- this.datastoreType = datastoreType;
- this.path = path;
- this.data = data;
- this.type = type;
- }
-
- @Override
- public void run() {
- try {
- LOG.trace("BgpUtil MDSAL task started ");
- WriteTransaction tx = getTransactionChain().newWriteOnlyTransaction();
- switch (type) {
- case WRITE:
- tx.put(datastoreType, path, data, true);
- break;
- case UPDATE:
- tx.merge(datastoreType, path, data, true);
- break;
- case DELETE:
- tx.delete(datastoreType, path);
- break;
- default:
- LOG.error("Invalid Transaction type: {}", type);
- }
- pendingWrTransaction.incrementAndGet();
- addFutureCallback(tx, path, data);
- LOG.trace("Transaction type: {} submitted", type);
- } catch (final Exception e) {
- LOG.error("TxChain transaction submission failed, re-init TxChain", e);
- initTransactionChain();
- }
- }
- }
-
-
- static <T extends DataObject> void addFutureCallback(WriteTransaction tx, final InstanceIdentifier<T> path,
- final T data) {
- Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
- @Override
- public void onSuccess(final Void result) {
- pendingWrTransaction.decrementAndGet();
- LOG.trace("DataStore entry success data:{} path:{} ", path);
- }
-
- @Override
- public void onFailure(final Throwable t) {
- pendingWrTransaction.decrementAndGet();
- LOG.error("DataStore entry failed data:{} path:{} cause:{} , retry initTransactionChain", data, path, t.getCause());
- }
- });
+ ActionableResource actResource = new ActionableResourceImpl(path.toString());
+ actResource.setAction(ActionableResource.DELETE);
+ actResource.setInstanceIdentifier(path);
+ actResource.setInstance(null);
+ bgpRoutesBufferQ.add(actResource);
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netvirt.bgpmanager;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.utils.batching.ResourceHandler;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class BgpVrfBatchHandler implements ResourceHandler {
+
+ public void update(WriteTransaction tx, LogicalDatastoreType datastoreType,
+ final InstanceIdentifier identifier, final Object original, final Object update) {
+ if ((update != null) && !(update instanceof DataObject)) {
+ return;
+ }
+ if (datastoreType != getDatastoreType()) {
+ return;
+ }
+ tx.merge(datastoreType, identifier, (DataObject) update, true);
+ }
+
+ public void create(WriteTransaction tx, final LogicalDatastoreType datastoreType,
+ final InstanceIdentifier identifier, final Object data) {
+ if ((data != null) && !(data instanceof DataObject)) {
+ return;
+ }
+ if (datastoreType != getDatastoreType()) {
+ return;
+ }
+ tx.put(datastoreType, identifier, (DataObject) data, true);
+ }
+
+ public void delete(WriteTransaction tx, final LogicalDatastoreType datastoreType,
+ final InstanceIdentifier identifier, final Object data) {
+ if ((data != null) && !(data instanceof DataObject)) {
+ return;
+ }
+ if (datastoreType != getDatastoreType()) {
+ return;
+ }
+ tx.delete(datastoreType, identifier);
+ }
+
+ public DataBroker getResourceBroker() {
+ return BgpUtil.getBroker();
+ }
+
+ public int getBatchSize() {
+ return BgpUtil.batchSize;
+ }
+
+ public int getBatchInterval() {
+ return BgpUtil.batchInterval;
+ }
+
+ public LogicalDatastoreType getDatastoreType() {
+ return LogicalDatastoreType.CONFIGURATION;
+ }
+}
+
StringBuilder sb = new StringBuilder();
int ip = 0, ret;
StringBuilder temp, temp2;
- char ch, gt = '>';
+ char ch, gt = '>', hashChar = '#';
inputBgpCmd.append("show " + cmd);
socket.close();
return;
}
- if (ip == (int) gt) {
- sb.append(gt);
+ if ((ip == (int) gt) || (ip == (int) hashChar)) {
+ if (ip == (int) gt) {
+ sb.append(gt);
+ } else {
+ sb.append(hashChar);
+ }
break;
} else if (ip == -1) {
System.out.println(sb.toString());
socket.close();
return;
}
- if (ip == (int) gt) {
+ if ((ip == (int) gt) || (ip == (int) hashChar)) {
break;
} else if (ip == -1) {
System.out.println(sb.toString());
socket.close();
return;
}
- if (ip == (int)gt) {
+ if (ip == (int)gt || ip == (int)hash) {
break;
} else if (ip == -1) {
LOGGER.error(sb.toString());
public int[] ints;
public List<String> irts;
public List<String> erts;
+ public long asNumber;
public static final int ignore = 0;
public BgpOp() {
strs = new String[3];
switch (op.type) {
case START:
setStartTS(System.currentTimeMillis());
+ LOGGER.debug("startBgp thrift call for AsId {}",op.asNumber);
result = bgpClient.startBgp(op.ints[0], op.strs[0],
op.ignore, op.ignore, op.ignore, op.ints[1], op.add);
+ LOGGER.debug("Result of startBgp thrift call for AsId {} : {}",op.asNumber,result);
startBGPresult = result;
break;
case STOP:
public void onUpdatePushRoute(String rd, String prefix, int plen, String nexthop, int label) {
try {
+ LOGGER.debug("Update on push route : rd {} prefix {} plen {}",rd,prefix,plen);
BgpConfigurationManager.onUpdatePushRoute(rd, prefix, plen, nexthop, label);
} catch (Throwable e) {
LOGGER.error("failed to handle update route ", e);
import org.opendaylight.genius.datastoreutils.AsyncClusteredDataChangeListenerBase;
import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
@Override
protected void remove(InstanceIdentifier<Port> identifier, Port del) {
LOG.trace("Port removed: {}", del);
- if(NeutronUtils.isPortVnicTypeNormal(del)) {
- return;
+ if(isVnicTypeDirectOrMacVtap(del)) {
+ removePort(del);
}
- removePort(del);
}
@Override
protected void update(InstanceIdentifier<Port> identifier, Port original, Port update) {
LOG.trace("Port changed to {}", update);
- if (NeutronUtils.isPortVnicTypeNormal(update)) {
+ if (!isVnicTypeDirectOrMacVtap(update)) {
LOG.trace("Port updated is normal {}", update.getUuid());
- if (!NeutronUtils.isPortVnicTypeNormal(original)) {
- LOG.trace("Original Port was direct {} so removing flows and cache entry if any", update.getUuid());
+ if (isVnicTypeDirectOrMacVtap(original)) {
+ LOG.trace("Original Port was direct/macvtap {} so removing flows and cache entry if any", update.getUuid());
removePort(original);
}
return;
}
- if (NeutronUtils.isPortVnicTypeNormal(original)) {
+ if (!isVnicTypeDirectOrMacVtap((original))) {
LOG.trace("Original port was normal and updated is direct. Calling addPort()");
addPort(update);
return;
@Override
protected void add(InstanceIdentifier<Port> identifier, Port add) {
LOG.trace("Port added {}", add);
- if(NeutronUtils.isPortVnicTypeNormal(add)) {
+ if(!isVnicTypeDirectOrMacVtap(add)) {
LOG.trace("Port is normal {}", add.getUuid());
return;
}
String macAddress = port.getMacAddress().getValue();
return macAddress;
}
+
+ private boolean isVnicTypeDirectOrMacVtap(Port port) {
+ PortBindingExtension portBinding = port.getAugmentation(PortBindingExtension.class);
+ if(portBinding == null || portBinding.getVnicType() == null) {
+ // By default, VNIC_TYPE is NORMAL
+ return false;
+ }
+ String vnicType = portBinding.getVnicType().trim().toLowerCase();
+ return (vnicType.equals("direct") || vnicType.equals("macvtap"));
+ }
}
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.List;
-import java.util.concurrent.Callable;
+import java.util.concurrent.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
import com.google.common.util.concurrent.ListenableFuture;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.genius.utils.batching.ActionableResource;
+import org.opendaylight.genius.utils.batching.ActionableResourceImpl;
+import org.opendaylight.genius.utils.batching.ResourceBatchingManager;
+import org.opendaylight.genius.utils.batching.ResourceHandler;
import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class FibManager extends AbstractDataChangeListener<VrfEntry> implements AutoCloseable{
+public class FibManager extends AbstractDataChangeListener<VrfEntry> implements AutoCloseable, ResourceHandler {
private static final Logger LOG = LoggerFactory.getLogger(FibManager.class);
private static final String FLOWID_PREFIX = "L3.";
private ListenerRegistration<DataChangeListener> listenerRegistration;
private static final BigInteger CLEAR_METADATA = BigInteger.valueOf(0);
public static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
+ private static final int PERIODICITY = 500;
+ private static Integer batchSize;
+ private static Integer batchInterval;
+
+ private static final int BATCH_SIZE = 1000;
+
+ private static BlockingQueue<ActionableResource> vrfEntryBufferQ = new LinkedBlockingQueue<>();
+ private ResourceBatchingManager resourceBatchingManager;
+
public FibManager(final DataBroker db) {
- super(VrfEntry.class);
- broker = db;
- registerListener(db);
+ super(VrfEntry.class);
+ broker = db;
+ registerListener(db);
+ batchSize = Integer.getInteger("batch.size");
+ if (batchSize == null) {
+ batchSize = BATCH_SIZE;
+ }
+ batchInterval = Integer.getInteger("batch.wait.time");
+ if (batchInterval == null) {
+ batchInterval = PERIODICITY;
+ }
+ resourceBatchingManager = ResourceBatchingManager.getInstance();
+ resourceBatchingManager.registerBatchableResource("FIB-VRFENTRY",vrfEntryBufferQ, this);
}
@Override
return InstanceIdentifier.create(FibEntries.class).child(VrfTables.class).child(VrfEntry.class);
}
+ public DataBroker getResourceBroker() {
+ return broker;
+ }
@Override
protected void add(final InstanceIdentifier<VrfEntry> identifier, final VrfEntry vrfEntry) {
String rd = identifier.firstKeyOf(VrfTables.class).getRouteDistinguisher();
LOG.info("ADD: Adding Fib Entry rd {} prefix {} nexthop {} label {}",
rd, vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), vrfEntry.getLabel());
- createFibEntries(identifier, vrfEntry);
+ if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
+ createFibEntries(identifier, vrfEntry);
+ } else {
+ ActionableResource actResource = new ActionableResourceImpl(rd.toString() + vrfEntry.getDestPrefix());
+ actResource.setAction(ActionableResource.CREATE);
+ actResource.setInstanceIdentifier(identifier);
+ actResource.setInstance(vrfEntry);
+ vrfEntryBufferQ.add(actResource);
+ leakRouteIfNeeded(identifier, vrfEntry, NwConstants.ADD_FLOW);
+ }
LOG.info("ADD: Added Fib Entry rd {} prefix {} nexthop {} label {}",
rd, vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), vrfEntry.getLabel());
- leakRouteIfNeeded(identifier, vrfEntry, NwConstants.ADD_FLOW);
}
@Override
String rd = identifier.firstKeyOf(VrfTables.class).getRouteDistinguisher();
LOG.info("REMOVE: Removing Fib Entry rd {} prefix {} nexthop {} label {}",
rd, vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), vrfEntry.getLabel());
- deleteFibEntries(identifier, vrfEntry);
+ if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
+ deleteFibEntries(identifier, vrfEntry);
+ } else {
+ ActionableResource actResource = new ActionableResourceImpl(rd.toString() + vrfEntry.getDestPrefix());
+ actResource.setAction(ActionableResource.DELETE);
+ actResource.setInstanceIdentifier(identifier);
+ actResource.setInstance(vrfEntry);
+ vrfEntryBufferQ.add(actResource);
+ leakRouteIfNeeded(identifier, vrfEntry, NwConstants.DEL_FLOW);
+ }
LOG.info("REMOVE: Removed Fib Entry rd {} prefix {} nexthop {} label {}",
rd, vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), vrfEntry.getLabel());
leakRouteIfNeeded(identifier, vrfEntry, NwConstants.DEL_FLOW);
@Override
protected void update(InstanceIdentifier<VrfEntry> identifier, VrfEntry original, VrfEntry update) {
Preconditions.checkNotNull(update, "VrfEntry should not be null or empty.");
- if (original.getAugmentation(SubnetRoute.class) != null && update.getAugmentation(SubnetRoute.class) == null)
- return;
String rd = identifier.firstKeyOf(VrfTables.class).getRouteDistinguisher();
LOG.info("UPDATE: Updating Fib Entries to rd {} prefix {} nexthop {} label {}",
rd, update.getDestPrefix(), update.getNextHopAddressList(), update.getLabel());
- createFibEntries(identifier, update);
+ if (RouteOrigin.value(update.getOrigin()) != RouteOrigin.BGP) {
+ createFibEntries(identifier, update);
+ } else {
+ ActionableResource actResource = new ActionableResourceImpl(rd.toString() + update.getDestPrefix());
+ actResource.setAction(ActionableResource.UPDATE);
+ actResource.setInstanceIdentifier(identifier);
+ actResource.setInstance(update);
+ actResource.setOldInstance(original);
+ vrfEntryBufferQ.add(actResource);
+ }
LOG.info("UPDATE: Updated Fib Entries to rd {} prefix {} nexthop {} label {}",
rd, update.getDestPrefix(), update.getNextHopAddressList(), update.getLabel());
}
+ public void create(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier, Object vrfEntry) {
+ if (vrfEntry instanceof VrfEntry) {
+ createFibEntries(tx, identifier, (VrfEntry)vrfEntry);
+ }
+ }
+
+ public void delete(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier, Object vrfEntry) {
+ if (vrfEntry instanceof VrfEntry) {
+ deleteFibEntries(tx, identifier, (VrfEntry) vrfEntry);
+ }
+ }
+
+ public void update(WriteTransaction tx, LogicalDatastoreType datastoreType, InstanceIdentifier identifier, Object original,
+ Object update) {
+ if ((original instanceof VrfEntry) && (update instanceof VrfEntry)) {
+ createFibEntries(tx, identifier, (VrfEntry)update);
+ }
+ }
+
+ public int getBatchSize() {
+ return batchSize;
+ }
+
+ public int getBatchInterval() {
+ return batchInterval;
+ }
+
+ public LogicalDatastoreType getDatastoreType() {
+ return LogicalDatastoreType.CONFIGURATION;
+ }
+
private void createFibEntries(final InstanceIdentifier<VrfEntry> vrfEntryIid, final VrfEntry vrfEntry) {
final VrfTablesKey vrfTableKey = vrfEntryIid.firstKeyOf(VrfTables.class);
public List<ListenableFuture<Void>> call() throws Exception {
WriteTransaction tx = broker.newWriteOnlyTransaction();
for (final VpnToDpnList curDpn : vpnToDpnList) {
- installSubnetRouteInFib(curDpn.getDpnId(),elanTag, rd, vpnId.longValue(), vrfEntry, tx);
+ if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+ installSubnetRouteInFib(curDpn.getDpnId(), elanTag, rd, vpnId.longValue(), vrfEntry, tx);
+ }
}
List<ListenableFuture<Void>> futures = new ArrayList<>();
futures.add(tx.submit());
WriteTransaction tx = broker.newWriteOnlyTransaction();
for (VpnToDpnList vpnDpn : vpnToDpnList) {
if ( !localDpnIdList.contains(vpnDpn.getDpnId())) {
- createRemoteFibEntry(vpnDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+ if (vpnDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+ createRemoteFibEntry(vpnDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+ }
}
}
List<ListenableFuture<Void>> futures = new ArrayList<>();
}
}
+
+ /*
+ Please note that the following createFibEntries will be invoked only for BGP Imported Routes.
+ The invocation of the following method is via create() callback from the MDSAL Batching Infrastructure
+ provided by ResourceBatchingManager
+ */
+ private void createFibEntries(WriteTransaction writeTx, final InstanceIdentifier<VrfEntry> vrfEntryIid, final VrfEntry vrfEntry) {
+ final VrfTablesKey vrfTableKey = vrfEntryIid.firstKeyOf(VrfTables.class);
+
+ final VpnInstanceOpDataEntry vpnInstance = getVpnInstance(vrfTableKey.getRouteDistinguisher());
+ Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available " + vrfTableKey.getRouteDistinguisher());
+ Preconditions.checkNotNull(vpnInstance.getVpnId(), "Vpn Instance with rd " + vpnInstance.getVrfId() + " has null vpnId!");
+
+ final Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
+ final String rd = vrfTableKey.getRouteDistinguisher();
+ if (vpnToDpnList != null) {
+ for (VpnToDpnList vpnDpn : vpnToDpnList) {
+ if (vpnDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+ createRemoteFibEntry(vpnDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, writeTx);
+ }
+ }
+ }
+ }
+
/*
* Returns true if the specified nexthop is the other endpoint in an
* InterVpnLink, regarding one of the VPN's point of view.
}
}
- private Collection<BigInteger> getDpnsForVpn(VpnInstanceOpDataEntry vpnInstance) {
- Collection<BigInteger> dpns = new HashSet<>();
- for(VpnToDpnList dpn : vpnInstance.getVpnToDpnList()) {
- dpns.add(dpn.getDpnId());
- }
-
- return dpns;
- }
-
private List<BigInteger> createLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
List<BigInteger> returnLocalDpnId = new ArrayList<BigInteger>();
Prefixes localNextHopInfo = getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
*/
public List<BigInteger> deleteLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
List<BigInteger> returnLocalDpnId = new ArrayList<>();
- BigInteger localDpnId = BigInteger.ZERO;
VpnNexthop localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
String localNextHopIP = vrfEntry.getDestPrefix();
if (localDpnIdList.size() <= 0) {
for (VpnToDpnList curDpn : vpnToDpnList) {
- deleteRemoteRoute(BigInteger.ZERO, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+ if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP) {
+ if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+ deleteRemoteRoute(BigInteger.ZERO, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+ }
+ } else {
+ deleteRemoteRoute(BigInteger.ZERO, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+ }
}
} else {
for (BigInteger localDpnId : localDpnIdList) {
for (VpnToDpnList curDpn : vpnToDpnList) {
if (!curDpn.getDpnId().equals(localDpnId)) {
- deleteRemoteRoute(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+ if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP) {
+ if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+ deleteRemoteRoute(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+ }
+ } else {
+ deleteRemoteRoute(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, tx);
+ }
}
}
}
}
+ /*
+ Please note that the following deleteFibEntries will be invoked only for BGP Imported Routes.
+ The invocation of the following method is via delete() callback from the MDSAL Batching Infrastructure
+ provided by ResourceBatchingManager
+ */
+ private void deleteFibEntries(WriteTransaction writeTx, final InstanceIdentifier<VrfEntry> identifier, final VrfEntry vrfEntry) {
+ final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class);
+
+ final String rd = vrfTableKey.getRouteDistinguisher();
+ final VpnInstanceOpDataEntry vpnInstance = getVpnInstance(vrfTableKey.getRouteDistinguisher());
+ if (vpnInstance == null) {
+ LOG.debug("VPN Instance for rd {} is not available from VPN Op Instance Datastore", rd);
+ return;
+ }
+ final Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
+ if (vpnToDpnList != null) {
+ for (VpnToDpnList curDpn : vpnToDpnList) {
+ if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) {
+ deleteRemoteRoute(BigInteger.ZERO, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry, writeTx);
+ }
+ }
+ }
+ }
+
public void deleteRemoteRoute(final BigInteger localDpnId, final BigInteger remoteDpnId,
final long vpnId, final VrfTablesKey vrfTableKey,
final VrfEntry vrfEntry, WriteTransaction tx) {
protected List<String> resolveAdjacency(final BigInteger remoteDpnId, final long vpnId, final VrfEntry vrfEntry,
String rd) {
List<String> adjacencyList = new ArrayList<>();
+ List<String> prefixIpList = new ArrayList<>();
LOG.trace("resolveAdjacency called with remotedpid {}, vpnId{}, VrfEntry {}", remoteDpnId, vpnId, vrfEntry);
try {
- Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
- List<String> prefixIpList;
- if (extra_route == null) {
- prefixIpList = Arrays.asList(vrfEntry.getDestPrefix());
- } else {
- prefixIpList = new ArrayList<>();
- for (String extraRouteIp : extra_route.getNexthopIpList()) {
- prefixIpList.add(extraRouteIp + "/32");
+ if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
+ Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+ if (extra_route == null) {
+ prefixIpList = Arrays.asList(vrfEntry.getDestPrefix());
+ } else {
+ prefixIpList = new ArrayList<>();
+ for (String extraRouteIp : extra_route.getNexthopIpList()) {
+ prefixIpList.add(extraRouteIp + "/32");
+ }
}
+ } else {
+ prefixIpList = Arrays.asList(vrfEntry.getDestPrefix());
}
for (String prefixIp : prefixIpList) {
BigInteger Dpn;
private static final long vpnId = 101L;
private static final long vpnIntfCnt = 2;
+ private static final Boolean isCleanupComplete = Boolean.FALSE;
private void SetupMocks() {
Dpn = BigInteger.valueOf(100000L);
@Override
public Long getVpnInterfaceCount() { return vpnIntfCnt; }
+ @Override
+ public Long getActiveDpnCount () {return 0L;}
+
@Override
public List<VpnToDpnList> getVpnToDpnList() {
List <VpnToDpnList> vpnToDpnLists = new ArrayList<>();
return new VpnToDpnListKey(Dpn);
}
+ @Override
+ public VpnToDpnList.DpnState getDpnState () { return VpnToDpnList.DpnState.Active;}
+
@Override
public <E extends Augmentation<VpnToDpnList>> E getAugmentation(
Class<E> augmentationType) {
+++ /dev/null
-/*
- * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netvirt.natservice.internal;
-
-import java.math.BigInteger;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.OdlL3vpnListener;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DpnInVpnListener implements OdlL3vpnListener {
- private static final Logger LOG = LoggerFactory.getLogger(DpnInVpnListener.class);
- private DataBroker dataBroker;
- private SNATDefaultRouteProgrammer defaultRouteProgrammer;
- private NaptSwitchHA naptSwitchHA;
- private IMdsalApiManager mdsalManager;
- private IdManagerService idManager;
-
- public DpnInVpnListener(DataBroker dataBroker) {
- this.dataBroker = dataBroker;
- }
-
- void setDefaultProgrammer(SNATDefaultRouteProgrammer defaultRouteProgrammer) {
- this.defaultRouteProgrammer = defaultRouteProgrammer;
- }
-
- void setNaptSwitchHA(NaptSwitchHA switchHA) {
- naptSwitchHA = switchHA;
- }
-
- void setMdsalManager(IMdsalApiManager mdsalManager) {
- this.mdsalManager = mdsalManager;
- }
-
- public void setIdManager(IdManagerService idManager) {
- this.idManager = idManager;
- }
-
- public void onAddDpnEvent(AddDpnEvent notification) {
-/*
- AddEventData eventData = notification.getAddEventData();
- BigInteger dpnId = eventData.getDpnId();
- String vpnName = eventData.getVpnName();
- LOG.info("Received add dpn {} in vpn {} event", dpnId, vpnName);
- String routerId = NatUtil.getRouterIdfromVpnId(dataBroker, vpnName);
- if (routerId != null) {
- //check router is associated to external network
- InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
- Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
- if (routerData.isPresent()) {
- Uuid networkId = routerData.get().getNetworkId();
- if(networkId != null) {
- LOG.debug("Router {} is associated with ext nw {}", routerId, networkId);
- long vpnId = NatUtil.readVpnId(dataBroker, vpnName);
- if(vpnId != NatConstants.INVALID_ID) {
- //Install default entry in FIB to SNAT table
- LOG.debug("Installing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName);
- defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId);
- } else {
- LOG.debug("Add DPN Event: Could not read vpnId for vpnName {}", vpnName);
- }
- if (routerData.get().isEnableSnat()) {
- LOG.info("SNAT enabled for router {}", routerId);
- handleSNATForDPN(dpnId, routerId);
- } else {
- LOG.info("SNAT is not enabled for router {} to handle addDPN event {}", routerId, dpnId);
- }
- }
- }
- }
-*/
- }
-
- void handleSNATForDPN(BigInteger dpnId, String routerName) {
- //Check if primary and secondary switch are selected, If not select the role
- //Install select group to NAPT switch
- //Install default miss entry to NAPT switch
-/*
- BigInteger naptSwitch;
- try {
- Long routerId = NatUtil.getVpnId(dataBroker, routerName);
- if (routerId == NatConstants.INVALID_ID) {
- LOG.error("Invalid routerId returned for routerName {}",routerName);
- return;
- }
- BigInteger naptId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
- if (naptId == null || naptId.equals(BigInteger.ZERO)) {
- LOG.debug("No Naptswitch is selected for router {}", routerName);
-
- naptSwitch = dpnId;
- boolean naptstatus = naptSwitchHA.updateNaptSwitch(routerName, naptSwitch);
- if(!naptstatus) {
- LOG.error("Failed to update newNaptSwitch {} for routername {}",naptSwitch,routerName);
- return;
- }
- LOG.debug("Switch {} is elected as NaptSwitch for router {}",dpnId,routerName);
-
- //installing group
- List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInPrimarySwitch();
- naptSwitchHA.installSnatGroupEntry(naptSwitch,bucketInfo,routerName);
-
- naptSwitchHA.installSnatFlows(routerName,routerId,naptSwitch);
-
- } else {
- LOG.debug("Napt switch with Id {} is already elected for router {}",naptId, routerName);
- naptSwitch = naptId;
-
- //installing group
- List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInNeighborSwitches(dpnId, routerName, naptSwitch);
- if (bucketInfo == null) {
- LOG.debug("Failed to populate bucketInfo for dpnId {} routername {} naptSwitch {}",dpnId,routerName,
- naptSwitch);
- return;
- }
- naptSwitchHA.installSnatGroupEntry(dpnId, bucketInfo, routerName);
- }
- // Install miss entry (table 26) pointing to group
- long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
- FlowEntity flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,NatConstants.ADD_FLOW);
- if (flowEntity == null) {
- LOG.debug("Failed to populate flowentity for router {} with dpnId {} groupId {}",routerName,dpnId,groupId);
- return;
- }
- LOG.debug("Successfully installed flow for dpnId {} router {} group {}",dpnId,routerName,groupId);
- mdsalManager.installFlow(flowEntity);
- } catch (Exception ex) {
- LOG.error("Exception in handleSNATForDPN method : {}",ex);
- }
-*/
- }
-
- public void onRemoveDpnEvent(RemoveDpnEvent notification) {
-/*
- RemoveEventData eventData = notification.getRemoveEventData();
- BigInteger dpnId = eventData.getDpnId();
- String vpnName = eventData.getVpnName();
- LOG.info("Received remove dpn {} in vpn {} event", dpnId, vpnName);
- String routerId = NatUtil.getRouterIdfromVpnId(dataBroker, vpnName);
- if (routerId != null) {
- //check router is associated to external network
- InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
- Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
- if (routerData.isPresent()) {
- Uuid networkId = routerData.get().getNetworkId();
- if(networkId != null) {
- LOG.debug("Router {} is associated with ext nw {}", routerId, networkId);
- long vpnId = NatUtil.readVpnId(dataBroker, vpnName);
- if(vpnId != NatConstants.INVALID_ID) {
- //Remove default entry in FIB
- LOG.debug("Removing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName);
- defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId);
- } else {
- LOG.debug("Remove DPN Event: Could not read vpnId for vpnName {}", vpnName);
- }
- if (routerData.get().isEnableSnat()) {
- LOG.info("SNAT enabled for router {}", routerId);
- removeSNATFromDPN(dpnId,routerId);
- } else {
- LOG.info("SNAT is not enabled for router {} to handle removeDPN event {}", routerId, dpnId);
- }
- }
- }
- }
-*/
- }
-
- /*void removeSNATFromDPN(BigInteger dpnId, String routerName) {
- //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
- //remove miss entry to NAPT switch
- //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
-
- Long routerId = NatUtil.getVpnId(dataBroker, routerName);
- if (routerId == NatConstants.INVALID_ID) {
- LOG.error("Invalid routerId returned for routerName {}",routerName);
- return;
- }
- BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
- if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
- LOG.debug("No naptSwitch is selected for router {}", routerName);
- return;
- }
- try {
- boolean naptStatus = naptSwitchHA.isNaptSwitchDown(routerName,dpnId,naptSwitch);
- if (!naptStatus) {
- LOG.debug("NaptSwitchDown: Switch with DpnId {} is not naptSwitch for router {}",
- dpnId, routerName);
- } else {
- naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName,naptSwitch);
- }
- } catch (Exception ex) {
- LOG.debug("Exception while handling naptSwitch down for router {} : {}",routerName,ex);
- }
-
- long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
- FlowEntity flowEntity = null;
- try {
- flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, NatConstants.DEL_FLOW);
- if (flowEntity == null) {
- LOG.debug("Failed to populate flowentity for router {} with dpnId {} groupIs {}",routerName,dpnId,groupId);
- return;
- }
- LOG.debug("NAT Service : Removing default SNAT miss entry flow entity {}",flowEntity);
- mdsalManager.removeFlow(flowEntity);
-
- } catch (Exception ex) {
- LOG.debug("NAT Service : Failed to remove default SNAT miss entry flow entity {} : {}",flowEntity,ex);
- return;
- }
- LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routername {}", dpnId, routerName);
-
- //remove group
- GroupEntity groupEntity = null;
- try {
- groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
- GroupTypes.GroupAll, null);
- LOG.info("NAT Service : Removing NAPT GroupEntity:{}", groupEntity);
- mdsalManager.removeGroup(groupEntity);
- } catch (Exception ex) {
- LOG.debug("NAT Service : Failed to remove group entity {} : {}",groupEntity,ex);
- return;
- }
- LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routerName {}", dpnId, routerName);
- }*/
-}
\ No newline at end of file
interfaceStateEventListener.setNaptManager(naptManager);
SNATDefaultRouteProgrammer defaultRouteProgrammer = new SNATDefaultRouteProgrammer(mdsalManager);
- DpnInVpnListener dpnInVpnListener = new DpnInVpnListener(dataBroker);
- dpnInVpnListener.setDefaultProgrammer(defaultRouteProgrammer);
- notificationService.registerNotificationListener(dpnInVpnListener);
externalRouterListener.setDefaultProgrammer(defaultRouteProgrammer);
natNodeEventListener = new NatNodeEventListener(dataBroker,naptSwitchHA);
- dpnInVpnListener.setNaptSwitchHA(naptSwitchHA);
- dpnInVpnListener.setMdsalManager(mdsalManager);
- dpnInVpnListener.setIdManager(idManager);
-
routerPortsListener = new RouterPortsListener(dataBroker);
RouterDpnChangeListener routerDpnChangeListener = new RouterDpnChangeListener(dataBroker);
key ip-address;
leaf ip-address { type string; }
}
+ leaf dpn-state {
+ description
+ "This flag indicates the state of the DPN.
+ Active state indicates atleast one vpn interface present on that DPN for the vpn.
+ Inactive state indicates no vpn interface present on that DPN for this vpn.";
+
+ type enumeration {
+ enum active {
+ value "0";
+ description
+ "Active state";
+ }
+ enum inactive {
+ value "1";
+ description
+ "Inactive state";
+ }
+ }
+ default "active";
+ }
}
+ leaf active-dpn-count { type uint32;}
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netvirt.vpnmanager;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.genius.mdsalutil.*;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.OdlL3vpnListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry
+ .VpnToDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public class DpnInVpnChangeListener implements OdlL3vpnListener {
+ private static final Logger LOG = LoggerFactory.getLogger(DpnInVpnChangeListener.class);
+ private DataBroker dataBroker;
+ private IMdsalApiManager mdsalManager;
+ private IdManagerService idManager;
+
+ public DpnInVpnChangeListener(DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ }
+
+ public void onAddDpnEvent(AddDpnEvent notification) {
+
+ }
+
+ public void onRemoveDpnEvent(RemoveDpnEvent notification) {
+
+ RemoveEventData eventData = notification.getRemoveEventData();
+ final String rd = eventData.getRd();
+ String vpnName = eventData.getVpnName();
+ BigInteger dpnId = eventData.getDpnId();
+
+ LOG.trace("Remove Dpn Event notification received for rd {} VpnName {} DpnId {}", rd , vpnName, dpnId);
+
+ synchronized (vpnName.intern()) {
+ InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
+ Optional<VpnInstanceOpDataEntry> vpnOpValue = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+
+ if (vpnOpValue.isPresent()) {
+ LOG.trace(" Active Dpn count {} in VpnInstOpData", vpnOpValue.get().getActiveDpnCount());
+ if (vpnOpValue.get().getActiveDpnCount() == 0) {
+ final Collection<VpnToDpnList> vpnToDpnList = vpnOpValue.get().getVpnToDpnList();
+
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+ dataStoreCoordinator.enqueueJob("VPN-" + vpnName,
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
+ deleteDpn(vpnToDpnList , rd , writeTxn);
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(writeTxn.submit());
+ return futures;
+ }
+ });
+
+ }
+ }
+ }
+ }
+
+ protected void deleteDpn(Collection<VpnToDpnList> vpnToDpnList, String rd, WriteTransaction writeTxn) {
+ for (final VpnToDpnList curDpn : vpnToDpnList) {
+ InstanceIdentifier<VpnToDpnList> VpnToDpnId = VpnUtil.getVpnToDpnListIdentifier(rd, curDpn.getDpnId());
+ writeTxn.delete(LogicalDatastoreType.OPERATIONAL, VpnToDpnId);
+ }
+ }
+}
+
import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
public class InterfaceStateChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
@Override
protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
- LOG.trace("Received interface {} up event", intrf);
- try {
- String interfaceName = intrf.getName();
- LOG.info("Received port UP event for interface {} ", interfaceName);
- org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
- configInterface = InterfaceUtils.getInterface(broker, interfaceName);
- BigInteger dpnId = BigInteger.ZERO;
- try{
- dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
- }catch(Exception e){
- LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. ", intrf.getName(), e);
- return;
- }
- if (configInterface != null) {
- if (!configInterface.getType().equals(Tunnel.class)) {
- // We service only VM interfaces and Router interfaces here.
- // We donot service Tunnel Interfaces here.
- // Tunnel events are directly serviced
- // by TunnelInterfacesStateListener present as part of VpnInterfaceManager
- final VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
- if (vpnInterface != null) {
- vpnInterfaceManager.processVpnInterfaceUp(dpnId, interfaceName, intrf.getIfIndex(), false);
- vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceUp(intrf);
- handleRouterInterfacesUpEvent(interfaceName);
+ LOG.trace("Received interface {} add event", intrf);
+ try {
+ final String interfaceName = intrf.getName();
+ LOG.info("Received interface add event for interface {} ", interfaceName);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
+ configInterface = InterfaceUtils.getInterface(broker, interfaceName);
+ if (configInterface != null) {
+ if (!configInterface.getType().equals(Tunnel.class)) {
+ // We service only VM interfaces and Router interfaces here.
+ // We donot service Tunnel Interfaces here.
+ // Tunnel events are directly serviced
+ // by TunnelInterfacesStateListener present as part of VpnInterfaceManager
+ final VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
+ if (vpnInterface != null) {
+ final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
+ final int ifIndex = intrf.getIfIndex();
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+ dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + intrf.getName(),
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+ vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, false, writeTxn);
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(writeTxn.submit());
+ return futures;
+ }
+ });
+ } else {
+ RouterInterface routerInterface = VpnUtil.getConfiguredRouterInterface(broker, interfaceName);
+ if (routerInterface != null) {
+ final String routerName = routerInterface.getRouterName();
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+ dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + intrf.getName(),
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+ handleRouterInterfacesUpEvent(routerName, interfaceName, writeTxn);
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(writeTxn.submit());
+ return futures;
+ }
+ });
+ } else {
+ LOG.info("Unable to process add for interface {} as it is not configured for vpn", interfaceName);
+ }
+ }
}
-
+ } else {
+ LOG.error("Unable to process add for interface {} ," +
+ "since Interface ConfigDS entry absent for the same", interfaceName);
}
+ } catch (Exception e) {
+ LOG.error("Exception caught in Interface Operational State Up event", e);
}
- } catch (Exception e) {
- LOG.error("Exception observed in handling addition for VPN Interface {}. ", intrf.getName(), e);
- }
}
@Override
protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
- LOG.trace("Received interface {} down event", intrf);
- try {
- String interfaceName = intrf.getName();
- LOG.info("Received port DOWN event for interface {} ", interfaceName);
- InstanceIdentifier<VpnInterface> id = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
- Optional<VpnInterface> existingVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
- if (!existingVpnInterface.isPresent()) {
- LOG.error("VPN Interface operational instance not available for interface {}, ignoring interface", interfaceName);
- return;
- }
- if (intrf != null && intrf.getType() != null && intrf.getType().equals(Tunnel.class)) {
- //withdraw all prefixes in all vpns for this dpn from bgp
- // FIXME: Blocked until tunnel event[vxlan/gre] support is available
- // vpnInterfaceManager.updatePrefixesForDPN(dpId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
- } else {
- BigInteger dpId = BigInteger.ZERO;
- try{
- dpId = InterfaceUtils.getDpIdFromInterface(intrf);
- }catch(Exception e){
- LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", intrf.getName(), e);
- dpId = existingVpnInterface.get().getDpnId();
+ LOG.trace("Received interface {} down event", intrf);
+ try {
+ final String interfaceName = intrf.getName();
+ LOG.info("Received port DOWN event for interface {} ", interfaceName);
+ if (intrf != null && intrf.getType() != null && intrf.getType().equals(Tunnel.class)) {
+ //withdraw all prefixes in all vpns for this dpn from bgp
+ // FIXME: Blocked until tunnel event[vxlan/gre] support is available
+ // vpnInterfaceManager.updatePrefixesForDPN(dpId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
+ } else {
+ BigInteger dpId = BigInteger.ZERO;
+ InstanceIdentifier<VpnInterface> id = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
+ Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (!optVpnInterface.isPresent()) {
+ LOG.debug("Interface {} is not a vpninterface, ignoring.", intrf.getName());
+ return;
+ }
+ VpnInterface vpnInterface = optVpnInterface.get();
+ try {
+ dpId = InterfaceUtils.getDpIdFromInterface(intrf);
+ } catch (Exception e){
+ LOG.warn("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", intrf.getName(), e);
+ dpId = vpnInterface.getDpnId();
+ }
+ final BigInteger dpnId = dpId;
+ final int ifIndex = intrf.getIfIndex();
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+ dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + intrf.getName(),
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+ vpnInterfaceManager.processVpnInterfaceDown(dpnId, interfaceName, ifIndex, false, false, writeTxn);
+ RouterInterface routerInterface = VpnUtil.getConfiguredRouterInterface(broker, interfaceName);
+ if (routerInterface != null) {
+ final String routerName = routerInterface.getRouterName();
+ handleRouterInterfacesDownEvent(routerName, interfaceName, dpnId, writeTxn);
+ }
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(writeTxn.submit());
+ return futures;
+ }
+ });
}
- vpnInterfaceManager.processVpnInterfaceDown(dpId, interfaceName, intrf.getIfIndex(), false, false);
- vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceDown(intrf);
- handleRouterInterfacesDownEvent(interfaceName,dpId);
+ } catch (Exception e) {
+ LOG.error("Exception observed in handling deletion of VPN Interface {}. ", intrf.getName(), e);
}
- } catch (Exception e) {
- LOG.error("Exception observed in handling deletion of VPN Interface {}. ", intrf.getName(), e);
- }
}
@Override
protected void update(InstanceIdentifier<Interface> identifier,
- Interface original, Interface update) {
- LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
- if(original.getOperStatus().equals(Interface.OperStatus.Unknown) || update.getOperStatus().equals(Interface.OperStatus.Unknown)){
- LOG.debug("Interface state change is from/to UNKNOWN. Ignoring the update event.");
- return;
- }
- String interfaceName = update.getName();
- BigInteger dpId = InterfaceUtils.getDpIdFromInterface(update);
- if (update != null) {
- if (update.getType().equals(Tunnel.class)) {
- /*
- // FIXME: Blocked until tunnel event[vxlan/gre] support is available
- BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(update);
- if(update.getOperStatus().equals(Interface.OperStatus.Up)) {
- //advertise all prefixes in all vpns for this dpn to bgp
- // vpnInterfaceManager.updatePrefixesForDPN(dpnId, VpnInterfaceManager.UpdateRouteAction.ADVERTISE_ROUTE);
- vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceUp(update);
- } else if(update.getOperStatus().equals(Interface.OperStatus.Down)) {
- //withdraw all prefixes in all vpns for this dpn from bgp
- // vpnInterfaceManager.updatePrefixesForDPN(dpnId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
- vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceDown(update);
- }*/
- } else {
- if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
- vpnInterfaceManager.processVpnInterfaceUp(dpId, interfaceName, update.getIfIndex(), true);
- vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceUp(update);
- } else if (update.getOperStatus().equals(Interface.OperStatus.Down)) {
- if (VpnUtil.isVpnInterfaceConfigured(broker, interfaceName)) {
- vpnInterfaceManager.processVpnInterfaceDown(dpId, interfaceName, update.getIfIndex(), true,
- false);
- vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceDown(update);
- }
- }
- }
- }
-
+ Interface original, Interface update) {
+ LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
+ final String interfaceName = update.getName();
+ if (original.getOperStatus().equals(Interface.OperStatus.Unknown) ||
+ update.getOperStatus().equals(Interface.OperStatus.Unknown)){
+ LOG.debug("Interface {} state change is from/to UNKNOWN. Ignoring the update event.", interfaceName);
+ return;
+ }
+ final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(update);
+ final int ifIndex = update.getIfIndex();
+ if (update != null) {
+ if (!update.getType().equals(Tunnel.class)) {
+ final VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
+ if (vpnInterface != null) {
+ if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+ dataStoreCoordinator.enqueueJob(interfaceName,
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+ vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnInterface, ifIndex,
+ true, writeTxn);
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(writeTxn.submit());
+ return futures;
+ }
+ });
+ } else if (update.getOperStatus().equals(Interface.OperStatus.Down)) {
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+ dataStoreCoordinator.enqueueJob(interfaceName,
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+ vpnInterfaceManager.processVpnInterfaceDown(dpnId, interfaceName, ifIndex, true, false, writeTxn);
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(writeTxn.submit());
+ return futures;
+ }
+ });
+ }
+ }
+ }
+ }
}
- void handleRouterInterfacesUpEvent(String interfaceName) {
- Optional<RouterInterface> optRouterInterface = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, VpnUtil.getRouterInterfaceId(interfaceName));
- if(optRouterInterface.isPresent()) {
- RouterInterface routerInterface = optRouterInterface.get();
- String routerName = routerInterface.getRouterName();
- LOG.debug("Handling UP event for router interface {} in Router {}", interfaceName, routerName);
- vpnInterfaceManager.addToNeutronRouterDpnsMap(routerName, interfaceName);
- } else {
- LOG.debug("No Router interface configured to handle UP event for {}", interfaceName);
- }
+ void handleRouterInterfacesUpEvent(String routerName, String interfaceName, WriteTransaction writeTxn) {
+ LOG.debug("Handling UP event for router interface {} in Router {}", interfaceName, routerName);
+ vpnInterfaceManager.addToNeutronRouterDpnsMap(routerName, interfaceName, writeTxn);
}
- void handleRouterInterfacesDownEvent(String interfaceName,BigInteger dpnId) {
- Optional<RouterInterface> optRouterInterface = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, VpnUtil.getRouterInterfaceId(interfaceName));
- if(optRouterInterface.isPresent()) {
- RouterInterface routerInterface = optRouterInterface.get();
- String routerName = routerInterface.getRouterName();
- LOG.debug("Handling DOWN event for router interface {} in Router {}", interfaceName, routerName);
- vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerName, interfaceName,dpnId);
- } else {
- LOG.debug("No Router interface configured to handle DOWN event for {}", interfaceName);
- }
+ void handleRouterInterfacesDownEvent(String routerName, String interfaceName, BigInteger dpnId, WriteTransaction writeTxn) {
+ LOG.debug("Handling DOWN event for router interface {} in Router {}", interfaceName, routerName);
+ vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerName, interfaceName, dpnId, writeTxn);
}
-}
+}
\ No newline at end of file
*/\r
package org.opendaylight.netvirt.vpnmanager;\r
\r
+import com.google.common.util.concurrent.ListenableFuture;\r
import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;\r
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;\r
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;\r
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;\r
import org.opendaylight.genius.mdsalutil.MDSALUtil;\r
import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;\r
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;\r
import org.slf4j.Logger;\r
import org.slf4j.LoggerFactory;\r
\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.concurrent.Callable;\r
+\r
public class RouterInterfaceListener extends AbstractDataChangeListener<Interfaces> {\r
private static final Logger LOG = LoggerFactory.getLogger(RouterInterfaceListener.class);\r
private ListenerRegistration<DataChangeListener> listenerRegistration;\r
protected void add(InstanceIdentifier<Interfaces> identifier, Interfaces interfaceInfo) {\r
LOG.trace("Add event - key: {}, value: {}", identifier, interfaceInfo);\r
final String routerId = identifier.firstKeyOf(RouterInterfaces.class).getRouterId().getValue();\r
- String interfaceName = interfaceInfo.getInterfaceId();\r
-\r
- MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, \r
- VpnUtil.getRouterInterfaceId(interfaceName), VpnUtil.getRouterInterface(interfaceName, routerId));\r
-\r
+ final String interfaceName = interfaceInfo.getInterfaceId();\r
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =\r
InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);\r
if (interfaceState != null) {\r
- LOG.debug("Handling interface {} in router {} add scenario", interfaceName, routerId);\r
- vpnInterfaceManager.addToNeutronRouterDpnsMap(routerId, interfaceName);\r
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();\r
+ dataStoreCoordinator.enqueueJob(interfaceName,\r
+ new Callable<List<ListenableFuture<Void>>>() {\r
+ @Override\r
+ public List<ListenableFuture<Void>> call() throws Exception {\r
+ WriteTransaction writeTxn = broker.newWriteOnlyTransaction();\r
+ LOG.debug("Handling interface {} in router {} add scenario", interfaceName, routerId);\r
+ writeTxn.put(LogicalDatastoreType.CONFIGURATION,\r
+ VpnUtil.getRouterInterfaceId(interfaceName),\r
+ VpnUtil.getRouterInterface(interfaceName, routerId), true);\r
+ vpnInterfaceManager.addToNeutronRouterDpnsMap(routerId, interfaceName, writeTxn);\r
+ List<ListenableFuture<Void>> futures = new ArrayList<>();\r
+ futures.add(writeTxn.submit());\r
+ return futures;\r
+ }\r
+ });\r
} else {\r
LOG.warn("Interface {} not yet operational to handle router interface add event in router {}", interfaceName, routerId);\r
}\r
protected void remove(InstanceIdentifier<Interfaces> identifier, Interfaces interfaceInfo) {\r
LOG.trace("Remove event - key: {}, value: {}", identifier, interfaceInfo);\r
final String routerId = identifier.firstKeyOf(RouterInterfaces.class).getRouterId().getValue();\r
- String interfaceName = interfaceInfo.getInterfaceId();\r
- vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerId, interfaceName);\r
+ final String interfaceName = interfaceInfo.getInterfaceId();\r
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();\r
+ dataStoreCoordinator.enqueueJob(interfaceName,\r
+ new Callable<List<ListenableFuture<Void>>>() {\r
+ @Override\r
+ public List<ListenableFuture<Void>> call() throws Exception {\r
+ WriteTransaction writeTxn = broker.newWriteOnlyTransaction();\r
+ vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerId, interfaceName, writeTxn);\r
+ List<ListenableFuture<Void>> futures = new ArrayList<>();\r
+ futures.add(writeTxn.submit());\r
+ return futures;\r
+ }\r
+ });\r
}\r
\r
@Override\r
--- /dev/null
+/*
+ * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netvirt.vpnmanager;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
+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.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+
+public class SubnetRouteInterfaceStateChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private VpnInterfaceManager vpnInterfaceManager;
+
+ public SubnetRouteInterfaceStateChangeListener(final DataBroker db, VpnInterfaceManager vpnInterfaceManager) {
+ super(Interface.class);
+ broker = db;
+ this.vpnInterfaceManager = vpnInterfaceManager;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("Interface listener Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), SubnetRouteInterfaceStateChangeListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Interface DataChange listener registration failed", e);
+ throw new IllegalStateException("Nexthop Manager registration Listener failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
+ LOG.trace("Received interface {} up event", intrf);
+ try {
+ String interfaceName = intrf.getName();
+ LOG.info("Received port UP event for interface {} ", interfaceName);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
+ configInterface = InterfaceUtils.getInterface(broker, interfaceName);
+ if (configInterface != null) {
+ if (!configInterface.getType().equals(Tunnel.class)) {
+ BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
+ vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceUp(dpnId, intrf.getName());
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("Exception observed in handling addition for VPN Interface {}. ", intrf.getName(), e);
+ }
+ }
+
+
+ private InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
+ LOG.trace("Received interface {} down event", intrf);
+ try {
+ String interfaceName = intrf.getName();
+ BigInteger dpnId = BigInteger.ZERO;
+ LOG.info("Received port DOWN event for interface {} ", interfaceName);
+ if (intrf != null && intrf.getType() != null && intrf.getType().equals(Tunnel.class)) {
+ //withdraw all prefixes in all vpns for this dpn from bgp
+ // FIXME: Blocked until tunnel event[vxlan/gre] support is available
+ // vpnInterfaceManager.updatePrefixesForDPN(dpId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
+ } else {
+ try {
+ dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
+ } catch (Exception e){
+ LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", intrf.getName(), e);
+ }
+ vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceDown(dpnId, intrf.getName());
+ }
+ } catch (Exception e) {
+ LOG.error("Exception observed in handling deletion of VPN Interface {}. ", intrf.getName(), e);
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> identifier,
+ Interface original, Interface update) {
+ LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
+ String interfaceName = update.getName();
+ BigInteger dpId = InterfaceUtils.getDpIdFromInterface(update);
+ if (update != null) {
+ if (!update.getType().equals(Tunnel.class)) {
+ if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
+ vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceUp(dpId, update.getName());
+ } else if (update.getOperStatus().equals(Interface.OperStatus.Down)) {
+ if (VpnUtil.isVpnInterfaceConfigured(broker, interfaceName)) {
+ vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceDown(dpId, update.getName());
+ }
+ }
+ }
+ }
+ }
+}
ITMTunnelLocType(int id) { this.type = id; }
public int getValue() { return type; }
}
+ public enum DCGWPresentStatus {
+ Invalid(0), Present(1), Absent(2);
+
+ private final int status;
+ DCGWPresentStatus(int id) { this.status = id; }
+ public int getValue() { return status; }
+ }
}
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterators;
import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
import org.opendaylight.netvirt.fibmanager.api.IFibManager;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.IsDcgwPresentOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.LabelRouteMap;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
+ .VpnInstanceOpDataEntryBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
+import java.util.concurrent.*;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
private ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
private ExecutorService executorService = Executors.newSingleThreadExecutor();
private InterfaceStateChangeListener interfaceListener;
+ private SubnetRouteInterfaceStateChangeListener subnetRouteInterfaceListener;
private TunnelInterfaceStateListener tunnelInterfaceStateListener;
private VpnInterfaceOpListener vpnInterfaceOpListener;
private ArpNotificationHandler arpNotificationHandler;
+ private DpnInVpnChangeListener dpnInVpnChangeListener;
private NotificationPublishService notificationPublishService;
private FibRpcService fibService;
protected enum UpdateRouteAction {
broker = db;
this.bgpManager = bgpManager;
interfaceListener = new InterfaceStateChangeListener(db, this);
+ subnetRouteInterfaceListener = new SubnetRouteInterfaceStateChangeListener(db, this);
vpnInterfaceOpListener = new VpnInterfaceOpListener();
arpNotificationHandler = new ArpNotificationHandler(this, broker);
vpnSubnetRouteHandler = new VpnSubnetRouteHandler(broker, bgpManager, this);
+ dpnInVpnChangeListener = new DpnInVpnChangeListener(broker);
tunnelInterfaceStateListener = new TunnelInterfaceStateListener(broker, this);
notificationService.registerNotificationListener(vpnSubnetRouteHandler);
notificationService.registerNotificationListener(arpNotificationHandler);
+ notificationService.registerNotificationListener(dpnInVpnChangeListener);
registerListener(db);
}
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
if(interfaceState != null){
- BigInteger dpnId = BigInteger.ZERO;
try{
- dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
+ final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
+ final int ifIndex = interfaceState.getIfIndex();
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+ dataStoreCoordinator.enqueueJob("VPNINTERFACE-"+ interfaceName,
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+ processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, false, writeTxn);
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(writeTxn.submit());
+ return futures;
+ }
+ });
}catch (Exception e){
LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. ", interfaceName, e);
return;
}
- processVpnInterfaceUp(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName,
- interfaceState.getIfIndex(), false);
} else {
LOG.info("Handling addition of VPN interface {} skipped as interfaceState is not available", interfaceName);
}
}
- protected void processVpnInterfaceUp(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceUp) {
+ protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface,
+ final int lPortTag, boolean isInterfaceUp, WriteTransaction writeTxn) {
- VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
- if(vpnInterface == null) {
- LOG.info("Unable to process add/up for interface {} as it is not configured", interfaceName);
- return;
- }
+ final String interfaceName = vpnInterface.getName();
if (!isInterfaceUp) {
- String vpnName = vpnInterface.getVpnInstanceName();
+ final String vpnName = vpnInterface.getVpnInstanceName();
LOG.info("Binding vpn service to interface {} ", interfaceName);
long vpnId = VpnUtil.getVpnId(broker, vpnName);
if (vpnId == VpnConstants.INVALID_ID) {
}
if (!waitForVpnInterfaceOpRemoval) {
// Add the VPNInterface and quit
- bindService(dpId, vpnName, interfaceName, lPortTag);
- updateDpnDbs(dpId, vpnName, interfaceName, true);
- processVpnInterfaceAdjacencies(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()),
- vpnInterface);
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+ dataStoreCoordinator.enqueueJob((interfaceName + dpId.toString()),
+ new UpdateDpnToVpnWorker(dpId, vpnName, interfaceName, lPortTag, true));
return;
}
}
}
// VPNInterface got removed, proceed with Add
synchronized (interfaceName.intern()) {
- bindService(dpId, vpnName, interfaceName, lPortTag);
- updateDpnDbs(dpId, vpnName, interfaceName, true);
- processVpnInterfaceAdjacencies(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()),
- vpnInterface);
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+ dataStoreCoordinator.enqueueJob((interfaceName + dpId.toString()),
+ new UpdateDpnToVpnWorker(dpId, vpnName, interfaceName, lPortTag, true));
}
} else {
synchronized (interfaceName.intern()) {
// Interface is retained in the DPN, but its Link Up.
// Advertise prefixes again for this interface to BGP
advertiseAdjacenciesForVpnToBgp(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()),
- vpnInterface);
+ vpnInterface, writeTxn);
}
}
}
- private void advertiseAdjacenciesForVpnToBgp(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
+
+ private class UpdateDpnToVpnWorker implements Callable<List<ListenableFuture<Void>>> {
+ BigInteger dpnId;
+ String vpnName;
+ String interfaceName;
+ boolean addToDpn;
+ int lPortTag;
+
+ public UpdateDpnToVpnWorker(BigInteger dpnId, String vpnName, String interfaceName,
+ int lPortTag, boolean addToDpn) {
+ this.dpnId= dpnId;
+ this.vpnName = vpnName;
+ this.interfaceName = interfaceName;
+ this.lPortTag = lPortTag;
+ this.addToDpn = addToDpn;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+ updateDpnDbs(dpnId, vpnName, interfaceName, addToDpn, writeTxn);
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(writeTxn.submit());
+ ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
+ Futures.addCallback(listenableFuture,
+ new UpdateDpnToVpnCallback(dpnId, vpnName, interfaceName, lPortTag, addToDpn));
+ return futures;
+ }
+ }
+
+
+ /**
+ * JobCallback class is used as a future callback for
+ * main and rollback workers to handle success and failure.
+ */
+ private class UpdateDpnToVpnCallback implements FutureCallback<List<Void>> {
+ BigInteger dpnId;
+ String vpnName;
+ String interfaceName;
+ boolean addToDpn;
+ int lPortTag;
+
+ public UpdateDpnToVpnCallback(BigInteger dpnId, String vpnName, String interfaceName,
+ int lPortTag, boolean addToDpn) {
+ this.dpnId= dpnId;
+ this.vpnName = vpnName;
+ this.interfaceName = interfaceName;
+ this.lPortTag = lPortTag;
+ this.addToDpn = addToDpn;
+ }
+
+ /**
+ * @param voids
+ * This implies that all the future instances have returned success. -- TODO: Confirm this
+ */
+ @Override
+ public void onSuccess(List<Void> voids) {
+ WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+ bindService(dpnId, vpnName, interfaceName, lPortTag, writeTxn);
+ processVpnInterfaceAdjacencies(dpnId, vpnName, interfaceName, writeTxn);
+ writeTxn.submit();
+ }
+
+ /**
+ *
+ * @param throwable
+ * This method is used to handle failure callbacks.
+ * If more retry needed, the retrycount is decremented and mainworker is executed again.
+ * After retries completed, rollbackworker is executed.
+ * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
+ */
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ LOG.warn("Job: failed with exception: {}", throwable.getStackTrace());
+ }
+ }
+
+
+ private void advertiseAdjacenciesForVpnToBgp(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier,
+ VpnInterface intf, WriteTransaction writeTxn) {
//Read NextHops
InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
}
}
- private void updateDpnDbs(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
+ private void updateDpnDbs(BigInteger dpId, String vpnName, String interfaceName, boolean add, WriteTransaction writeTxn) {
long vpnId = VpnUtil.getVpnId(broker, vpnName);
if (dpId == null) {
dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, interfaceName);
}
if(!dpId.equals(BigInteger.ZERO)) {
if(add)
- updateMappingDbs(vpnId, dpId, interfaceName, vpnName);
+ updateMappingDbs(vpnId, dpId, interfaceName, vpnName, writeTxn);
else
- removeFromMappingDbs(vpnId, dpId, interfaceName, vpnName);
+ removeFromMappingDbs(vpnId, dpId, interfaceName, vpnName, writeTxn);
}
-
}
- private void bindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
+ private void bindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, int lPortTag,
+ WriteTransaction writeTxn) {
int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
VpnConstants.L3VPN_SERVICE_IDENTIFIER, priority,
VpnConstants.COOKIE_VM_INGRESS_TABLE, instructions);
- VpnUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
- InterfaceUtils.buildServiceId(vpnInterfaceName, VpnConstants.L3VPN_SERVICE_IDENTIFIER), serviceInfo);
+ writeTxn.put(LogicalDatastoreType.CONFIGURATION,
+ InterfaceUtils.buildServiceId(vpnInterfaceName, VpnConstants.L3VPN_SERVICE_IDENTIFIER), serviceInfo, true);
makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
- vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW);
+ vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW, writeTxn);
makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
- vpnId, ArpReplyOrRequest.REPLY, NwConstants.ADD_FLOW);
+ vpnId, ArpReplyOrRequest.REPLY, NwConstants.ADD_FLOW, writeTxn);
}
- private void processVpnInterfaceAdjacencies(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier,
- VpnInterface intf) {
- String intfName = intf.getName();
- synchronized (intfName) {
+ private void processVpnInterfaceAdjacencies(BigInteger dpnId, String vpnName, String interfaceName,
+ WriteTransaction writeTxn) {
+ InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
+
+ synchronized (interfaceName) {
// Read NextHops
InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
List<Adjacency> value = new ArrayList<>();
// Get the rd of the vpn instance
- String rd = getRouteDistinguisher(intf.getVpnInstanceName());
+ String rd = getRouteDistinguisher(vpnName);
String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
if (nextHopIp == null){
- LOG.error("NextHop for interface {} is null", intfName);
+ LOG.error("NextHop for interface {} is null", interfaceName);
return;
}
- List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(intf.getVpnInstanceName());
- LOG.trace("NextHops for interface {} are {}", intfName, nextHops);
+
+ List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
+
+ LOG.trace("NextHops for interface {} are {}", interfaceName, nextHops);
for (Adjacency nextHop : nextHops) {
String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
- long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
- .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
+ long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+ VpnUtil.getNextHopLabelKey((rd == null) ? vpnName
+ : rd, prefix));
List<String> adjNextHop = nextHop.getNextHopIpList();
value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIpList(
(adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : Arrays.asList(nextHopIp))
.setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
+
if (nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
- LOG.trace("Adding prefix {} to interface {} for vpn {}", prefix, intfName, intf.getVpnInstanceName());
- VpnUtil.syncUpdate(
- broker,
+ LOG.trace("Adding prefix {} to interface {} for vpn {}", prefix, interfaceName, vpnName);
+ writeTxn.merge(
LogicalDatastoreType.OPERATIONAL,
VpnUtil.getPrefixToInterfaceIdentifier(
- VpnUtil.getVpnId(broker, intf.getVpnInstanceName()), prefix),
- VpnUtil.getPrefixToInterface(dpnId, intf.getName(), prefix));
+ VpnUtil.getVpnId(broker, vpnName), prefix),
+ VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix), true);
} else {
//Extra route adjacency
- // FIXME 4: To be fixed with VPNManager patch
- LOG.trace("Adding prefix {} and nexthopList {} as extra-route for vpn", nextHop.getIpAddress(), nextHop.getNextHopIpList(), intf.getVpnInstanceName() );
- VpnUtil.syncUpdate(
- broker,
+ LOG.trace("Adding prefix {} and nexthopList {} as extra-route for vpn", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName);
+ writeTxn.merge(
LogicalDatastoreType.OPERATIONAL,
VpnUtil.getVpnToExtrarouteIdentifier(
- (rd != null) ? rd : intf.getVpnInstanceName(), nextHop.getIpAddress()),
- VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIpList()));
+ (rd != null) ? rd : vpnName, nextHop.getIpAddress()),
+ VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIpList()), true);
}
-
}
Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
- VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug, dpnId, Boolean.FALSE);
- InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
- VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface);
- long vpnId = VpnUtil.getVpnId(broker, intf.getVpnInstanceName());
+
+ VpnInterface opInterface = VpnUtil.getVpnInterface(interfaceName, vpnName, aug, dpnId, Boolean.FALSE);
+ InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
+ writeTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, true);
+ long vpnId = VpnUtil.getVpnId(broker, vpnName);
+
for (Adjacency nextHop : aug.getAdjacency()) {
long label = nextHop.getLabel();
List<String> nextHopList = new ArrayList<>(nextHop.getNextHopIpList());
if (rd != null) {
+
addToLabelMapper(label, dpnId, nextHop.getIpAddress(), nextHopList, vpnId,
- intfName, null,false, rd);
- addPrefixToBGP(rd, nextHop.getIpAddress(), nextHopIp, label);
+ interfaceName, null,false, rd);
+ addPrefixToBGP(rd, nextHop.getIpAddress(), nextHopIp, label, writeTxn);
//TODO: ERT - check for VPNs importing my route
for (VpnInstance vpn : vpnsToImportRoute) {
String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
if (vpnRd != null) {
LOG.debug("Exporting route with rd {} prefix {} nexthop {} label {} to VPN {}", vpnRd, nextHop.getIpAddress(), nextHopIp, label, vpn);
- VpnUtil.addFibEntryToDS(broker, vpnRd, nextHop.getIpAddress(), nextHopIp, (int) label, RouteOrigin.SELF_IMPORTED);
+ VpnUtil.addFibEntryToDS(broker, vpnRd, nextHop.getIpAddress(), nextHopIp, (int) label, RouteOrigin.SELF_IMPORTED, writeTxn);
}
}
} else {
// ### add FIB route directly
- VpnUtil.addFibEntryToDS(broker, intf.getVpnInstanceName(), nextHop.getIpAddress(), nextHopIp,
- (int) label, RouteOrigin.STATIC);
+ VpnUtil.addFibEntryToDS(broker, vpnName, nextHop.getIpAddress(), nextHopIp,
+ (int) label, RouteOrigin.STATIC, writeTxn);
}
}
}
}
private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName,
- long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow){
+ long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow, WriteTransaction writeTxn){
List<MatchInfo> matches = new ArrayList<MatchInfo>();
BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, BigInteger.valueOf(vpnId));
BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_INTERFACE_TABLE, flowRef,
NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0,
VpnUtil.getCookieArpFlow(lPortTag), matches, instructions);
-
- if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
- LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
- mdsalManager.installFlow(flowEntity);
+ Flow flow = flowEntity.getFlowBuilder().build();
+ String flowId = flowEntity.getFlowId();
+ FlowKey flowKey = new FlowKey( new FlowId(flowId));
+ Node nodeDpn = buildDpnNode(dpId);
+
+ InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flowKey).build();
+
+ if (writeTxn != null) {
+ if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
+ LOG.debug("Creating ARP Flow for interface {}", vpnInterfaceName);
+ writeTxn.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, true);
+ } else {
+ LOG.debug("Deleting ARP Flow for interface {}", vpnInterfaceName);
+ writeTxn.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
+ }
} else {
- LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
- mdsalManager.removeFlow(flowEntity);
+ if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
+ LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
+ mdsalManager.installFlow(flowEntity);
+ } else {
+ LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
+ mdsalManager.removeFlow(flowEntity);
+ }
}
}
+ //TODO: How to handle the below code, its a copy paste from MDSALManager.java
+ private Node buildDpnNode(BigInteger dpnId) {
+ NodeId nodeId = new NodeId("openflow:" + dpnId);
+ Node nodeDpn = new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build();
+
+ return nodeDpn;
+ }
+
private String getRouteDistinguisher(String vpnName) {
InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
.child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
return rd;
}
- private synchronized void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
+ private void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName,
+ WriteTransaction writeTxn) {
String routeDistinguisher = getRouteDistinguisher(vpnName);
String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
- InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
- Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
- org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
- vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
-
- if (dpnInVpn.isPresent()) {
- VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id.child(
- org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
- .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
- new VpnInterfacesKey(intfName)), vpnInterface);
- } else {
- VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
- VpnUtil.getVpnInstanceOpDataIdentifier(rd),
- VpnUtil.getVpnInstanceOpDataBuilder(rd, vpnId, vpnName));
- VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
- List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
- .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = new ArrayList<>();
- vpnInterfaces.add(vpnInterface);
- VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id,
- vpnToDpnList.setVpnInterfaces(vpnInterfaces).build());
-
- /**
- * FIXME: DC Gateway tunnel should be built dynamically
- //this is the first VM in this VPN on the DPN, may be a new DPN has come up,
- //if tunnel to DC GW does not exist, create it
- //if(!tunnelExists(dpnID, bgpManager.getDCGWIP()))
- String dcGW = bgpManager.getDCGwIP();
- if(dcGW != null && !dcGW.isEmpty())
- {
- LOG.debug("Building tunnel from DPN {} to DC GW {}", dpnId, dcGW);
- itmProvider.buildTunnelFromDPNToDCGW(dpnId, new IpAddress(dcGW.toCharArray()));
- }*/
- fibManager.populateFibOnNewDpn(dpnId, vpnId, (rd == null) ? vpnName : rd);
- publishAddNotification(dpnId, vpnName, rd);
- //TODO: IRT - import local routes to vpn. check for the VPNs exporting the routes
- //FIXME: do we need to handle here. since already routes are imported to this vpn
+ synchronized (vpnName.intern()) {
+ InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op
+ .data.entry.vpn.to.dpn.list.VpnInterfaces
+ vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+ if (dpnInVpn.isPresent()) {
+ if (writeTxn != null) {
+ writeTxn.put(LogicalDatastoreType.OPERATIONAL, id.child(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance
+ .op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
+ new VpnInterfacesKey(intfName)), vpnInterface, true);
+ } else {
+ VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id.child(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance
+ .op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
+ new VpnInterfacesKey(intfName)), vpnInterface);
+ }
+ } else {
+
+ /*
+ * Increment the active dpn count in VpnInstanceOpData.
+ * ActiveDpnCount will be decremented when all the VpnInt in that Dpn are removed.
+ */
+ InstanceIdentifier<VpnInstanceOpDataEntry> vpnInsOpDataId = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
+ Optional<VpnInstanceOpDataEntry> vpnInstOpData = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, vpnInsOpDataId);
+
+ java.lang.Long activeDpnCnt = vpnInstOpData.get().getActiveDpnCount();
+
+ VpnInstanceOpDataEntryBuilder builder =
+ new VpnInstanceOpDataEntryBuilder(vpnInstOpData.get()).setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnName).setActiveDpnCount(++activeDpnCnt);
+
+ if (writeTxn != null) {
+ writeTxn.merge(LogicalDatastoreType.OPERATIONAL,
+ vpnInsOpDataId,
+ builder.build(), true);
+ } else {
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
+ vpnInsOpDataId,
+ builder.build());
+ }
+
+ VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId).setDpnState(VpnToDpnList.DpnState.Active);
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = new ArrayList<>();
+ vpnInterfaces.add(vpnInterface);
+ if (writeTxn != null) {
+ writeTxn.merge(LogicalDatastoreType.OPERATIONAL, id,
+ vpnToDpnList.setVpnInterfaces(vpnInterfaces).build(), true);
+ } else {
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id,
+ vpnToDpnList.setVpnInterfaces(vpnInterfaces).build());
+ }
+ /**
+ * FIXME: DC Gateway tunnel should be built dynamically
+ //this is the first VM in this VPN on the DPN, may be a new DPN has come up,
+ //if tunnel to DC GW does not exist, create it
+ //if(!tunnelExists(dpnID, bgpManager.getDCGWIP()))
+ String dcGW = bgpManager.getDCGwIP();
+ if(dcGW != null && !dcGW.isEmpty())
+ {
+ LOG.debug("Building tunnel from DPN {} to DC GW {}", dpnId, dcGW);
+ itmProvider.buildTunnelFromDPNToDCGW(dpnId, new IpAddress(dcGW.toCharArray()));
+ }*/
+ fibManager.populateFibOnNewDpn(dpnId, vpnId, (rd == null) ? vpnName : rd);
+ publishAddNotification(dpnId, vpnName, rd);
+ //TODO: IRT - import local routes to vpn. check for the VPNs exporting the routes
+ //FIXME: do we need to handle here. since already routes are imported to this vpn
+ }
}
}
importSubnetRouteForNewVpn(rd, prefix, nh, (int)label, route);
} else {
LOG.info("Importing fib entry rd {} prefix {} nexthop {} label {} to vpn {}", vpnRd, prefix, nh, label, vpn.getVpnInstanceName());
- VpnUtil.addFibEntryToDS(broker, vpnRd, prefix, nh, (int)label, RouteOrigin.SELF_IMPORTED);
+ VpnUtil.addFibEntryToDS(broker, vpnRd, prefix, nh, (int)label, RouteOrigin
+ .SELF_IMPORTED, null);
}
}
} catch (Exception e) {
}
}
- private synchronized void removeFromMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
+ private void removeFromMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName,
+ WriteTransaction writeTxn) {
//TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
- String rd = VpnUtil.getVpnRd(broker, vpnName);
- InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
- Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
- if (dpnInVpn.isPresent()) {
- List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
- .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
- org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
- currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
-
- if (vpnInterfaces.remove(currVpnInterface)) {
- if (vpnInterfaces.isEmpty()) {
- List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
- if (ipAddresses == null || ipAddresses.isEmpty()) {
- LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
- VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id, VpnUtil.DEFAULT_CALLBACK);
- fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
- publishRemoveNotification(dpnId, vpnName, rd);
+ synchronized (vpnName.intern()) {
+ String rd = VpnUtil.getVpnRd(broker, vpnName);
+ InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (dpnInVpn.isPresent()) {
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn
+ .instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
+ currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+ if (vpnInterfaces.remove(currVpnInterface)) {
+ if (vpnInterfaces.isEmpty()) {
+ List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
+ if (ipAddresses == null || ipAddresses.isEmpty()) {
+
+ /*
+ * Mark the DPN state as Inactive as the Vpnintf list is empty.
+ * This DPN will be removed in DpnToVpnChangeListner only if its
+ * inactive and ActiveDpnCount is zero.
+ */
+ VpnToDpnListBuilder vpnToDpnList =
+ new VpnToDpnListBuilder(dpnInVpn.get())
+ .setDpnId(dpnId)
+ .setDpnState(VpnToDpnList.DpnState.Inactive)
+ .setVpnInterfaces(vpnInterfaces);
+
+ if (writeTxn != null) {
+ writeTxn.merge(LogicalDatastoreType.OPERATIONAL, id , vpnToDpnList.build(), true);
+ } else {
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnList.build());
+ }
+
+ InstanceIdentifier<VpnInstanceOpDataEntry> vpnInstOpDataId = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
+ Optional<VpnInstanceOpDataEntry> vpnInstOpData = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, vpnInstOpDataId);
+
+ java.lang.Long activeDpnCnt = vpnInstOpData.get().getActiveDpnCount();
+
+ VpnInstanceOpDataEntryBuilder builder =
+ new VpnInstanceOpDataEntryBuilder(vpnInstOpData.get()).setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnName).setActiveDpnCount(--activeDpnCnt);
+
+ if (writeTxn != null) {
+ writeTxn.merge(LogicalDatastoreType.OPERATIONAL, vpnInstOpDataId , builder.build(), true);
+ } else {
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, vpnInstOpDataId, builder.build());
+ }
+
+ LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
+ fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
+ publishRemoveNotification(dpnId, vpnName, rd);
+ } else {
+ LOG.debug("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}", vpnName, dpnId);
+ }
} else {
- LOG.debug("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}", vpnName, dpnId);
+ if (writeTxn != null) {
+ writeTxn.delete(LogicalDatastoreType.OPERATIONAL, id.child(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op
+ .data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
+ new VpnInterfacesKey(intfName)));
+ } else {
+ VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
+ new VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
+ }
}
- } else {
- VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
- org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
- .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
- new VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
}
}
}
}
- private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label) {
+ private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label, WriteTransaction writeTxn) {
+
try {
LOG.info("ADD: Adding Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
- bgpManager.addPrefix(rd, prefix, Arrays.asList(nextHopIp), (int)label, RouteOrigin.STATIC);
+ VpnUtil.addFibEntryToDS(broker, rd, prefix, nextHopIp, (int)label, RouteOrigin.STATIC, writeTxn);
+ bgpManager.advertisePrefix(rd, prefix, Arrays.asList(nextHopIp), (int)label);
LOG.info("ADD: Added Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
} catch(Exception e) {
LOG.error("Add prefix failed", e);
public void remove( InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
- String interfaceName = key.getName();
+ final String interfaceName = key.getName();
InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
Optional<VpnInterface> existingVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
- if(existingVpnInterface.isPresent()){
+ if (existingVpnInterface.isPresent()){
BigInteger dpnId = BigInteger.ZERO;
Boolean dpnIdRetrieved = Boolean.FALSE;
if(interfaceState != null){
}catch (Exception e){
LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", interfaceName, e);
}
+ } else {
+ LOG.error("Unable to retrieve interfaceState for interface {} , quitting ", interfaceName);
+ return;
}
if(dpnIdRetrieved == Boolean.FALSE){
LOG.info("dpnId for {} has not been retrieved yet. Fetching from vpn interface operational DS", interfaceName);
dpnId = existingVpnInterface.get().getDpnId();
}
- processVpnInterfaceDown(dpnId, interfaceName, interfaceState.getIfIndex(), false, true);
+ final int ifIndex = interfaceState.getIfIndex();
+ final BigInteger dpId = dpnId;
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+ dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+ processVpnInterfaceDown(dpId, interfaceName, ifIndex, false, true, writeTxn);
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(writeTxn.submit());
+ waitForFibToRemoveVpnPrefix(interfaceName);
+ return futures;
+ }
+ });
+ //processVpnInterfaceDown(dpnId, interfaceName, interfaceState.getIfIndex(), false, true);
}else{
LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
}
}
- protected void processVpnInterfaceDown(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceStateDown, boolean isConfigRemoval) {
+ protected void processVpnInterfaceDown(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceStateDown,
+ boolean isConfigRemoval, WriteTransaction writeTxn) {
InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
if (!isInterfaceStateDown) {
synchronized (interfaceName.intern()) {
LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
return;
}else{
- String vpnName = vpnInterface.getVpnInstanceName();
+ final String vpnName = vpnInterface.getVpnInstanceName();
if(!vpnInterface.isScheduledForRemove()){
- VpnUtil.updateVpnInterface(broker, vpnInterface.getName(), vpnInterface.getDpnId(), vpnInterface.getVpnInstanceName(), Boolean.TRUE);
- removeAdjacenciesFromVpn(dpId, identifier, vpnInterface);
+ VpnUtil.updateVpnInterface(broker, interfaceName, dpId, vpnName, Boolean.TRUE, writeTxn);
+ removeAdjacenciesFromVpn(dpId, interfaceName, vpnInterface.getVpnInstanceName(), writeTxn);
LOG.info("Unbinding vpn service from interface {} ", interfaceName);
- unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown, isConfigRemoval);
+ unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown, isConfigRemoval, writeTxn);
}else{
LOG.info("Unbinding vpn service for interface {} has already been scheduled by a different event ", interfaceName);
return;
}
}
}
-
- // FIB didn't get a chance yet to clean up this VPNInterface
- // Let us give it a chance here !
- LOG.info("VPN Interface {} removal waiting for FIB to clean up ! ", interfaceName);
- try {
- Runnable notifyTask = new VpnNotifyTask();
- vpnIntfMap.put(interfaceName, notifyTask);
- synchronized (notifyTask) {
- try {
- notifyTask.wait(VpnConstants.PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS);
- } catch (InterruptedException e) {
- }
- }
- } finally {
- vpnIntfMap.remove(interfaceName);
- }
} else {
synchronized (interfaceName.intern()) {
// Interface is retained in the DPN, but its Link Down.
}
- private void removeAdjacenciesFromVpn(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
+ private void waitForFibToRemoveVpnPrefix(String interfaceName) {
+ // FIB didn't get a chance yet to clean up this VPNInterface
+ // Let us give it a chance here !
+ LOG.info("VPN Interface {} removal waiting for FIB to clean up ! ", interfaceName);
+ try {
+ Runnable notifyTask = new VpnNotifyTask();
+ vpnIntfMap.put(interfaceName, notifyTask);
+ synchronized (notifyTask) {
+ try {
+ notifyTask.wait(VpnConstants.PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS);
+ } catch (InterruptedException e) {
+ }
+ }
+ } finally {
+ vpnIntfMap.remove(interfaceName);
+ }
+ }
+
+ private void removeAdjacenciesFromVpn(final BigInteger dpnId, final String interfaceName, final String vpnName,
+ WriteTransaction writeTxn) {
//Read NextHops
+ InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
- String rd = VpnUtil.getVpnRd(broker, intf.getVpnInstanceName());
- LOG.trace("removeAdjacenciesFromVpn: For interface {} RD recovered for vpn {} as rd {}", intf.getName(),
- intf.getVpnInstanceName(), rd);
+ String rd = VpnUtil.getVpnRd(broker, vpnName);
+ LOG.trace("removeAdjacenciesFromVpn: For interface {} RD recovered for vpn {} as rd {}", interfaceName,
+ vpnName, rd);
if (adjacencies.isPresent()) {
List<Adjacency> nextHops = adjacencies.get().getAdjacency();
// This is a primary adjacency
nhList = nextHop.getNextHopIpList();
}
- if (rd.equals(intf.getVpnInstanceName())) {
+ if (rd.equals(vpnName)) {
//this is an internal vpn - the rd is assigned to the vpn instance name;
//remove from FIB directly
for(String nh : nhList) {
- VpnUtil.removeFibEntryFromDS(broker, intf.getVpnInstanceName(), nextHop.getIpAddress(), nh);
+ VpnUtil.removeFibEntryFromDS(broker, vpnName, nextHop.getIpAddress(), nh, writeTxn);
}
} else {
-
- List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(intf.getVpnInstanceName());
+ List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
for (String nh : nextHop.getNextHopIpList()) {
//IRT: remove routes from other vpns importing it
- removePrefixFromBGP(rd, nextHop.getIpAddress(), nh);
+ removePrefixFromBGP(rd, nextHop.getIpAddress(), nh, writeTxn);
for (VpnInstance vpn : vpnsToImportRoute) {
String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
if (vpnRd != null) {
LOG.info("Removing Exported route with rd {} prefix {} from VPN {}", vpnRd, nextHop.getIpAddress(), vpn.getVpnInstanceName());
- VpnUtil.removeFibEntryFromDS(broker, vpnRd, nextHop.getIpAddress(), nh);
+ VpnUtil.removeFibEntryFromDS(broker, vpnRd, nextHop.getIpAddress(), nh, writeTxn);
}
}
}
}
String ip = nextHop.getIpAddress().split("/")[0];
VpnPortipToPort vpnPortipToPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(broker,
- intf.getVpnInstanceName(), ip);
+ vpnName, ip);
if (vpnPortipToPort != null && !vpnPortipToPort.isConfig()) {
LOG.trace("VpnInterfaceManager removing adjacency for Interface {} ip {} from VpnPortData Entry",
vpnPortipToPort.getPortName(),ip);
- VpnUtil.removeVpnPortFixedIpToPort(broker, intf.getVpnInstanceName(), ip);
+ VpnUtil.removeVpnPortFixedIpToPort(broker, vpnName, ip);
}
}
}
private void unbindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName,
- int lPortTag, boolean isInterfaceStateDown, boolean isConfigRemoval) {
+ int lPortTag, boolean isInterfaceStateDown, boolean isConfigRemoval,
+ WriteTransaction writeTxn) {
if (!isInterfaceStateDown && isConfigRemoval) {
- MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION,
+ writeTxn.delete(LogicalDatastoreType.CONFIGURATION,
InterfaceUtils.buildServiceId(vpnInterfaceName,
VpnConstants.L3VPN_SERVICE_IDENTIFIER));
}
long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
- vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW);
+ vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW, writeTxn);
makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
- vpnId, ArpReplyOrRequest.REPLY, NwConstants.DEL_FLOW);
+ vpnId, ArpReplyOrRequest.REPLY, NwConstants.DEL_FLOW, writeTxn);
}
- private void removePrefixFromBGP(String rd, String prefix, String nextHop) {
- VpnUtil.removeFibEntryFromDS(broker, rd, prefix, nextHop);
+ private void removePrefixFromBGP(String rd, String prefix, String nextHop, WriteTransaction writeTxn) {
+ VpnUtil.removeFibEntryFromDS(broker, rd, prefix, nextHop, writeTxn);
try {
LOG.info("VPN WITHDRAW: Removing Fib Entry rd {} prefix {}", rd, prefix);
+ VpnUtil.removeFibEntryFromDS(broker, rd, prefix, nextHop, writeTxn);
bgpManager.withdrawPrefix(rd, prefix); // TODO: Might be needed to include nextHop here
LOG.info("VPN WITHDRAW: Removed Fib Entry rd {} prefix {}", rd, prefix);
} catch(Exception e) {
}
public synchronized void addSubnetRouteFibEntryToDS(String rd, String vpnName, String prefix, String nextHop, int label,
- long elantag, BigInteger dpnId) {
+ long elantag, BigInteger dpnId, WriteTransaction writeTxn) {
SubnetRoute route = new SubnetRouteBuilder().setElantag(elantag).build();
RouteOrigin origin = RouteOrigin.STATIC; // Only case when a route is considered as directly connected
VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
setVrfEntry(vrfEntryList).build();
- VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
+ if (writeTxn != null) {
+ writeTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
+ } else {
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
+ }
List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
if (vpnsToImportRoute.size() > 0) {
VrfEntry importingVrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
- .setLabel((long)label).setOrigin(RouteOrigin.SELF_IMPORTED.getValue())
+ .setLabel((long) label).setOrigin(RouteOrigin.SELF_IMPORTED.getValue())
.addAugmentation(SubnetRoute.class, route).build();
List<VrfEntry> importingVrfEntryList = Arrays.asList(importingVrfEntry);
for (VpnInstance vpnInstance : vpnsToImportRoute) {
String importingRd = vpnInstance.getIpv4Family().getRouteDistinguisher();
InstanceIdentifier<VrfTables> importingVrfTableId = InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(importingRd)).build();
VrfTables importingVrfTable = new VrfTablesBuilder().setRouteDistinguisher(importingRd).setVrfEntry(importingVrfEntryList).build();
- VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable);
+ if (writeTxn != null) {
+ writeTxn.merge(LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable, true);
+ } else {
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable);
+ }
}
}
}
}
public synchronized void deleteSubnetRouteFibEntryFromDS(String rd, String prefix, String vpnName){
- VpnUtil.removeFibEntryFromDS(broker, rd, prefix, null /* nextHopToRemove */);
+ VpnUtil.removeFibEntryFromDS(broker, rd, prefix, null /* nextHopToRemove */, null);
List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
for (VpnInstance vpnInstance : vpnsToImportRoute) {
String importingRd = vpnInstance.getIpv4Family().getRouteDistinguisher();
LOG.info("Deleting imported subnet route rd {} prefix {} from vpn {}", rd, prefix, vpnInstance.getVpnInstanceName());
- VpnUtil.removeFibEntryFromDS(broker, importingRd, prefix, null);
+ VpnUtil.removeFibEntryFromDS(broker, importingRd, prefix, null, null);
}
}
VpnUtil.leakRoute(broker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, destination, newLabel);
} else {
if (rd != null) {
- addPrefixToBGP(rd, destination, nextHop, label);
+ addPrefixToBGP(rd, destination, nextHop, label, null);
} else {
// ### add FIB route directly
- VpnUtil.addFibEntryToDS(broker, routerID, destination, nextHop, label, RouteOrigin.STATIC);
+ VpnUtil.addFibEntryToDS(broker, routerID, destination, nextHop, label, RouteOrigin.STATIC, null);
}
}
}
}
if (rd != null) {
- removePrefixFromBGP(rd, destination, nextHop);
+ removePrefixFromBGP(rd, destination, nextHop, null);
} else {
// ### add FIB route directly
- VpnUtil.removeFibEntryFromDS(broker, routerID, destination, nextHop);
+ VpnUtil.removeFibEntryFromDS(broker, routerID, destination, nextHop, null);
}
}
VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), pref.getIpAddress()),
VpnUtil.DEFAULT_CALLBACK);
synchronized (interfaceName.intern()) {
- updateDpnDbs(pref.getDpnId(), del.getVpnInstanceName(), interfaceName, false);
+ updateDpnDbs(pref.getDpnId(), del.getVpnInstanceName(), interfaceName, false, null);
}
}
-// Long ifCnt = 0L;
-// //ifCnt = vpnInstOp.getVpnInterfaceCount();
-// LOG.trace("VpnInterfaceOpListener removed: interface name {} rd {} vpnName {} Intf count {}",
-// interfaceName, rd, vpnName, ifCnt);
-// if ((ifCnt != null) && (ifCnt > 0)) {
-// VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
-// VpnUtil.getVpnInstanceOpDataIdentifier(rd),
-// VpnUtil.updateIntfCntInVpnInstOpData(ifCnt - 1, rd), VpnUtil.DEFAULT_CALLBACK);
-// }
}
} else {
LOG.error("rd not retrievable as vpninstancetovpnid for vpn {} is absent, trying rd as ", vpnName, vpnName);
}
//increment the vpn interface count in Vpn Instance Op Data
- //Long ifCnt = 0L;
VpnInstanceOpDataEntry vpnInstOp = null;
-// InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
-// updId = VpnUtil.getVpnInstanceToVpnIdIdentifier(update.getVpnInstanceName());
-// Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> updVpnInstance
-// = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, updId);
-//
-// if (updVpnInstance.isPresent()) {
-// String rd = null;
-// rd = updVpnInstance.get().getVrfId();
-//
-// vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
-//
-// if (vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
-// ifCnt = vpnInstOp.getVpnInterfaceCount();
-// }
-//
-// LOG.trace("VpnInterfaceOpListener update: interface name {} rd {} interface count in updated Vpn Op Instance {}", interfaceName, rd, ifCnt);
-//
-// VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
-// VpnUtil.getVpnInstanceOpDataIdentifier(rd),
-// VpnUtil.updateIntfCntInVpnInstOpData(ifCnt + 1, rd), VpnUtil.DEFAULT_CALLBACK);
-// }
-//
InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
origId = VpnUtil.getVpnInstanceToVpnIdIdentifier(original.getVpnInstanceName());
Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> origVpnInstance
}
}
}
-// VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
-// VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
-// prefixToInterface.get().getIpAddress()),
-// VpnUtil.DEFAULT_CALLBACK);
synchronized (interfaceName.intern()) {
for (Prefixes prefix : prefixToInterfaceList) {
- updateDpnDbs(prefix.getDpnId(), original.getVpnInstanceName(), interfaceName, false);
+ updateDpnDbs(prefix.getDpnId(), original.getVpnInstanceName(), interfaceName, false, null);
}
}
}
}
notifyTaskIfRequired(interfaceName);
-// if (vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
-// ifCnt = vpnInstOp.getVpnInterfaceCount();
-// } else {
-// LOG.debug("VpnInterfaceOpListener update: Vpn interface count not recoverable from original, to handle update for rd {}", rd);
-// return;
-// }
-// LOG.trace("VpnInterfaceOpListener update: interface name {} rd {} interface count in original Vpn Op Instance {}", interfaceName, rd, ifCnt);
-//
-// if (ifCnt > 0) {
-// VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
-// VpnUtil.getVpnInstanceOpDataIdentifier(rd),
-// VpnUtil.updateIntfCntInVpnInstOpData(ifCnt - 1, rd), VpnUtil.DEFAULT_CALLBACK);
-// }
-// }
}
@Override
protected void add(InstanceIdentifier<VpnInterface> identifier, VpnInterface add) {
- final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
- String interfaceName = key.getName();
-
- //increment the vpn interface count in Vpn Instance Op Data
-// Long ifCnt = 0L;
-// String rd = getRouteDistinguisher(add.getVpnInstanceName());
-// if(rd == null || rd.isEmpty()) rd = add.getVpnInstanceName();
-// VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
-// if(vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
-// ifCnt = vpnInstOp.getVpnInterfaceCount();
-// }
-
-// LOG.trace("VpnInterfaceOpListener add: interface name {} rd {} interface count in Vpn Op Instance {}", interfaceName, rd, ifCnt);
-
-// VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
-// VpnUtil.getVpnInstanceOpDataIdentifier(rd),
-// VpnUtil.updateIntfCntInVpnInstOpData(ifCnt + 1, rd), VpnUtil.DEFAULT_CALLBACK);
-
}
}
tunTypeVal = VpnConstants.ITMTunnelLocType.Invalid.getValue();
}
LOG.trace("tunTypeVal is {}", tunTypeVal);
+ long dcgwPresentStatus = VpnConstants.DCGWPresentStatus.Invalid.getValue();
+ if (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
+ Future<RpcResult<IsDcgwPresentOutput>> result;
+ try {
+ result = itmProvider.isDcgwPresent(new IsDcgwPresentInputBuilder()
+ .setDcgwIp(destTepIp)
+ .build());
+ RpcResult<IsDcgwPresentOutput> rpcResult = result.get();
+ if (!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to isDcgwPresent {} returned with Errors {}", destTepIp, rpcResult.getErrors());
+ } else {
+ dcgwPresentStatus = rpcResult.getResult().getRetVal();
+ }
+ } catch (Exception e) {
+ LOG.warn("Exception {} when querying for isDcgwPresent {}, trace {}", e, destTepIp, e.getStackTrace());
+ }
+ }
if (vpnInstances.isPresent()) {
List<VpnInstance> vpnInstanceList = vpnInstances.get().getVpnInstance();
rd, adjacency.getIpAddress(), srcTepIp, destTepIp);
}
if (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
- bgpManager.advertisePrefix( rd, adjacency.getIpAddress(),
- adjacency.getNextHopIpList(),
- adjacency.getLabel().intValue());
fibManager.populateFibOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
}
}
new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId()),
vpnId, rd, adjacency.getIpAddress(), srcTepIp, destTepIp);
}
- if (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
+ if ((tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) &&
+ (dcgwPresentStatus == VpnConstants.DCGWPresentStatus.Absent.getValue())) {
bgpManager.withdrawPrefix(rd, adjacency.getIpAddress());
fibManager.cleanUpDpnForVpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
}
// if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
// fibManager.cleanUpDpnForVpn(dpnId, VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
// }
+ // Go through all the VrfEntries and withdraw and readvertise the prefixes to BGP for which the nextHop is the SrcTepIp
+ if ((action == UpdateRouteAction.ADVERTISE_ROUTE) &&
+ (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue())) {
+ List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(broker, rd);
+ if (vrfEntries != null) {
+ for (VrfEntry vrfEntry : vrfEntries) {
+ String destPrefix = vrfEntry.getDestPrefix().trim();
+ int vpnLabel = vrfEntry.getLabel().intValue();
+ List<String> nextHops = vrfEntry.getNextHopAddressList();
+ if (nextHops.contains(srcTepIp.trim())) {
+ bgpManager.withdrawPrefix(rd, destPrefix);
+ bgpManager.advertisePrefix(rd, destPrefix, nextHops, vpnLabel);
+ }
+ }
+ }
+ }
} else {
LOG.trace("dpnInVpn check failed for srcDpnId {}.", srcDpnId);
}
.child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
}
- protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName) {
+ protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeTxn) {
BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
if(dpId.equals(BigInteger.ZERO)) {
LOG.warn("Could not retrieve dp id for interface {} to handle router {} association model", vpnInterfaceName, routerName);
.OPERATIONAL, routerDpnListIdentifier);
RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
if (optionalRouterDpnList.isPresent()) {
- MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
- RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface);
+ writeTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
+ RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface, true);
} else {
- MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
- getRouterId(routerName),
- new RouterDpnListBuilder().setRouterId(routerName).build());
- //VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
+ RouterDpnListBuilder builder = new RouterDpnListBuilder();
+ builder.setRouterId(routerName);
DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
List<RouterInterfaces> routerInterfaces = new ArrayList<>();
routerInterfaces.add(routerInterface);
- MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier,
- dpnVpnList.setRouterInterfaces(routerInterfaces).build());
+ builder.setDpnVpninterfacesList(Arrays.asList(dpnVpnList.build()));
+ writeTxn.merge(LogicalDatastoreType.OPERATIONAL,
+ getRouterId(routerName),
+ new RouterDpnListBuilder().setRouterId(routerName).build(), true);
}
}
- protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName) {
+ protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeTxn) {
BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
if(dpId.equals(BigInteger.ZERO)) {
LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
if (routerInterfaces.isEmpty()) {
- MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
+ if (writeTxn != null) {
+ writeTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
+ } else {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
+ }
} else {
- MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
- RouterInterfaces.class,
- new RouterInterfacesKey(vpnInterfaceName)));
+ if (writeTxn != null) {
+ writeTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
+ RouterInterfaces.class,
+ new RouterInterfacesKey(vpnInterfaceName)));
+ } else {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
+ RouterInterfaces.class,
+ new RouterInterfacesKey(vpnInterfaceName)));
+ }
}
}
}
}
- protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,BigInteger dpId) {
+ protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId, WriteTransaction writeTxn) {
if(dpId.equals(BigInteger.ZERO)) {
LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
return;
if (optionalRouterDpnList.isPresent()) {
List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
-
if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
if (routerInterfaces.isEmpty()) {
- MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
+ writeTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
} else {
- MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
+ writeTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
RouterInterfaces.class,
new RouterInterfacesKey(vpnInterfaceName)));
}
import java.util.List;
import java.util.concurrent.*;
-import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.*;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
public class VpnManager extends AbstractDataChangeListener<VpnInstance> implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(VpnManager.class);
Thread.sleep(timeout);
} catch (java.lang.InterruptedException e) {
}
-// Runnable notifyTask = new VpnNotifyTask();
-// synchronized (rd.intern()) {
-// try {
-// vpnOpMap.put(rd, notifyTask);
-// synchronized (notifyTask) {
-// try {
-// notifyTask.wait(timeout);
-// } catch (InterruptedException e) {
-// }
-// }
-// } finally {
-// vpnOpMap.remove(rd);
-// }
-// }
// Check current interface count
vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
}
LOG.info("Returned out of waiting for Op Data removal for rd {}, vpnname {}", rd, vpnName);
}
-
-
@Override
protected void remove(InstanceIdentifier<VpnInstance> identifier, VpnInstance del) {
LOG.trace("Remove VPN event key: {}, value: {}", identifier, del);
- String vpnName = del.getVpnInstanceName();
- String rd = del.getIpv4Family().getRouteDistinguisher();
- long vpnId = VpnUtil.getVpnId(broker, vpnName);
+ final String vpnName = del.getVpnInstanceName();
+ final String rd = del.getIpv4Family().getRouteDistinguisher();
+ final long vpnId = VpnUtil.getVpnId(broker, vpnName);
+ Optional<VpnInstanceOpDataEntry> vpnOpValue = null;
//TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
- Optional<VpnInstanceOpDataEntry> vpnOpValue = null;
- if ((rd != null) && (!rd.isEmpty())) {
- vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
- VpnUtil.getVpnInstanceOpDataIdentifier(rd));
- } else {
- vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
- VpnUtil.getVpnInstanceOpDataIdentifier(vpnName));
+ try {
+ if ((rd != null) && (!rd.isEmpty())) {
+ vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd));
+ } else {
+ vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(vpnName));
+ }
+ } catch (Exception e) {
+ LOG.error("Exception when attempting to retrieve VpnInstanceOpDataEntry for VPN {}. ", vpnName, e);
+ return;
}
- if ((rd != null) && (!rd.isEmpty())) {
- waitForOpRemoval(rd, vpnName);
- } else {
- waitForOpRemoval(vpnName, vpnName);
+ if (vpnOpValue == null || !vpnOpValue.isPresent()) {
+ LOG.error("Unable to retrieve VpnInstanceOpDataEntry for VPN {}. ", vpnName);
+ return;
}
- // Clean up VpnInstanceToVpnId from Config DS
- VpnUtil.removeVpnIdToVpnInstance(broker, vpnId);
- VpnUtil.removeVpnInstanceToVpnId(broker, vpnName);
- LOG.trace("Removed vpnIdentifier for rd{} vpnname {}", rd, vpnName);
- if (rd != null) {
- synchronized (rd.intern()) {
- try {
- bgpManager.deleteVrf(rd);
- } catch (Exception e) {
- LOG.error("Exception when removing VRF from BGP for RD {} in VPN {} exception " + e, rd, vpnName);
- }
- }
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+ dataStoreCoordinator.enqueueJob("VPN-" + vpnName,
+ new DeleteVpnInstanceWorker(idManager, broker, del));
+ }
- // Clean up VPNExtraRoutes Operational DS
- VpnUtil.removeVpnExtraRouteForVpn(broker, rd);
+ private class DeleteVpnInstanceWorker implements Callable<List<ListenableFuture<Void>>> {
+ IdManagerService idManager;
+ DataBroker broker;
+ VpnInstance vpnInstance;
+
+ public DeleteVpnInstanceWorker(IdManagerService idManager,
+ DataBroker broker,
+ VpnInstance value) {
+ this.idManager = idManager;
+ this.broker = broker;
+ this.vpnInstance = value;
+ }
- // Clean up VPNInstanceOpDataEntry
- VpnUtil.removeVpnOpInstance(broker, rd);
- } else {
- // Clean up FIB Entries Config DS
- synchronized (vpnName.intern()) {
- VpnUtil.removeVrfTableForVpn(broker, vpnName);
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ final String vpnName = vpnInstance.getVpnInstanceName();
+ final String rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
+ final long vpnId = VpnUtil.getVpnId(broker, vpnName);
+ WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+ if ((rd != null) && (!rd.isEmpty())) {
+ waitForOpRemoval(rd, vpnName);
+ } else {
+ waitForOpRemoval(vpnName, vpnName);
}
- // Clean up VPNExtraRoutes Operational DS
- VpnUtil.removeVpnExtraRouteForVpn(broker, vpnName);
+ // Clean up VpnInstanceToVpnId from Config DS
+ VpnUtil.removeVpnIdToVpnInstance(broker, vpnId, writeTxn);
+ VpnUtil.removeVpnInstanceToVpnId(broker, vpnName, writeTxn);
+
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(writeTxn.submit());
+ LOG.trace("Removed vpnIdentifier for rd{} vpnname {}", rd, vpnName);
+ if (rd != null) {
+ synchronized (rd.intern()) {
+ try {
+ bgpManager.deleteVrf(rd);
+ } catch (Exception e) {
+ LOG.error("Exception when removing VRF from BGP for RD {} in VPN {} exception " + e, rd, vpnName);
+ }
+ }
- // Clean up VPNInstanceOpDataEntry
- VpnUtil.removeVpnOpInstance(broker, vpnName);
- }
+ // Clean up VPNExtraRoutes Operational DS
+ VpnUtil.removeVpnExtraRouteForVpn(broker, rd, null);
+
+ // Clean up VPNInstanceOpDataEntry
+ VpnUtil.removeVpnOpInstance(broker, rd, null);
+ } else {
+ // Clean up FIB Entries Config DS
+ synchronized (vpnName.intern()) {
+ VpnUtil.removeVrfTableForVpn(broker, vpnName, null);
+ }
+ // Clean up VPNExtraRoutes Operational DS
+ VpnUtil.removeVpnExtraRouteForVpn(broker, vpnName, null);
+
+ // Clean up VPNInstanceOpDataEntry
+ VpnUtil.removeVpnOpInstance(broker, vpnName, null);
+ }
+ // Clean up PrefixToInterface Operational DS
+ VpnUtil.removePrefixToInterfaceForVpnId(broker, vpnId, null);
- // Clean up PrefixToInterface Operational DS
- VpnUtil.removePrefixToInterfaceForVpnId(broker, vpnId);
+ // Clean up L3NextHop Operational DS
+ VpnUtil.removeL3nexthopForVpnId(broker, vpnId, null);
- // Clean up L3NextHop Operational DS
- VpnUtil.removeL3nexthopForVpnId(broker, vpnId);
+ // Release the ID used for this VPN back to IdManager
+ VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnName);
- // Release the ID used for this VPN back to IdManager
- VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnName);
+ return futures;
+ }
}
@Override
protected void update(InstanceIdentifier<VpnInstance> identifier,
- VpnInstance original, VpnInstance update) {
+ VpnInstance original, VpnInstance update) {
LOG.trace("Update VPN event key: {}, value: {}", identifier, update);
}
@Override
- protected void add(InstanceIdentifier<VpnInstance> identifier, VpnInstance value) {
+ protected void add(final InstanceIdentifier<VpnInstance> identifier, final VpnInstance value) {
LOG.trace("Add VPN event key: {}, value: {}", identifier, value);
+ final VpnAfConfig config = value.getIpv4Family();
+ final String rd = config.getRouteDistinguisher();
+ final String vpnName = value.getVpnInstanceName();
+
+ DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
+ dataStoreCoordinator.enqueueJob("VPN-" + vpnName,
+ new AddVpnInstanceWorker(idManager, vpnInterfaceManager, broker, value));
+ }
+
+ private class AddVpnInstanceWorker implements Callable<List<ListenableFuture<Void>>> {
+ IdManagerService idManager;
+ VpnInterfaceManager vpnInterfaceManager;
+ VpnInstance vpnInstance;
+ DataBroker broker;
+
+ public AddVpnInstanceWorker(IdManagerService idManager,
+ VpnInterfaceManager vpnInterfaceManager,
+ DataBroker broker,
+ VpnInstance value) {
+ this.idManager = idManager;
+ this.vpnInterfaceManager = vpnInterfaceManager;
+ this.broker = broker;
+ this.vpnInstance = value;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ final VpnAfConfig config = vpnInstance.getIpv4Family();
+ final String rd = config.getRouteDistinguisher();
+ WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
+ addVpnInstance(vpnInstance, writeTxn);
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(writeTxn.submit());
+ ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
+ if (rd != null) {
+ Futures.addCallback(listenableFuture,
+ new AddBgpVrfWorker(config , vpnInstance.getVpnInstanceName()));
+ }
+ return futures;
+ }
+ }
+
+ private void addVpnInstance(VpnInstance value, WriteTransaction writeTxn) {
VpnAfConfig config = value.getIpv4Family();
String rd = config.getRouteDistinguisher();
String vpnInstanceName = value.getVpnInstanceName();
long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnInstanceName);
LOG.trace("VPN instance to ID generated.");
org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
- vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(vpnInstanceName, vpnId, (rd != null) ? rd
- : vpnInstanceName);
+ vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(vpnInstanceName, vpnId, (rd != null) ? rd
+ : vpnInstanceName);
- syncWrite(LogicalDatastoreType.CONFIGURATION, VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
- vpnInstanceToVpnId, DEFAULT_CALLBACK);
+ if (writeTxn != null) {
+ writeTxn.put(LogicalDatastoreType.CONFIGURATION, VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
+ vpnInstanceToVpnId, true);
+ } else {
+ syncWrite(LogicalDatastoreType.CONFIGURATION, VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
+ vpnInstanceToVpnId, DEFAULT_CALLBACK);
+ }
- VpnIds
+ org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds
vpnIdToVpnInstance = VpnUtil.getVpnIdToVpnInstance(vpnId, value.getVpnInstanceName(),
- (rd != null) ? rd : value.getVpnInstanceName(), (rd != null)/*isExternalVpn*/) ;
+ (rd != null) ? rd : value.getVpnInstanceName(), (rd != null)/*isExternalVpn*/);
- syncWrite(LogicalDatastoreType.CONFIGURATION,
- VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
- vpnIdToVpnInstance, DEFAULT_CALLBACK);
+ if (writeTxn != null) {
+ writeTxn.put(LogicalDatastoreType.CONFIGURATION,
+ VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
+ vpnIdToVpnInstance, true);
+ } else {
+ syncWrite(LogicalDatastoreType.CONFIGURATION,
+ VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
+ vpnIdToVpnInstance, DEFAULT_CALLBACK);
+ }
IFibManager fibManager = vpnInterfaceManager.getFibManager();
try {
LOG.error(e.getMessage());
}
- if(rd == null) {
+ if (rd == null) {
VpnInstanceOpDataEntryBuilder builder =
- new VpnInstanceOpDataEntryBuilder().setVrfId(vpnInstanceName).setVpnId(vpnId)
- .setVpnInstanceName(vpnInstanceName)
- .setVpnInterfaceCount(0L);
- syncWrite(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(vpnInstanceName),
- builder.build(), DEFAULT_CALLBACK);
-
+ new VpnInstanceOpDataEntryBuilder().setVrfId(vpnInstanceName).setVpnId(vpnId)
+ .setVpnInstanceName(vpnInstanceName)
+ .setVpnInterfaceCount(0L).setActiveDpnCount(0L);
+ if (writeTxn != null) {
+ writeTxn.merge(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(vpnInstanceName),
+ builder.build(), true);
+ } else {
+ syncWrite(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(vpnInstanceName),
+ builder.build(), DEFAULT_CALLBACK);
+ }
} else {
VpnInstanceOpDataEntryBuilder builder =
- new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnInstanceName)
- .setVpnInterfaceCount(0L);
- syncWrite(LogicalDatastoreType.OPERATIONAL,
- VpnUtil.getVpnInstanceOpDataIdentifier(rd),
- builder.build(), DEFAULT_CALLBACK);
+ new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnInstanceName)
+ .setVpnInterfaceCount(0L).setActiveDpnCount(0L);
- List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
+ if (writeTxn != null) {
+ writeTxn.merge(LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+ builder.build(), true);
+ } else {
+ syncWrite(LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+ builder.build(), DEFAULT_CALLBACK);
+ }
+ }
+ }
- List<String> ertList = new ArrayList<String>();
- List<String> irtList = new ArrayList<String>();
- for (VpnTarget vpnTarget : vpnTargetList) {
- if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
- ertList.add(vpnTarget.getVrfRTValue());
- }
- if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
- irtList.add(vpnTarget.getVrfRTValue());
- }
- if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
- ertList.add(vpnTarget.getVrfRTValue());
- irtList.add(vpnTarget.getVrfRTValue());
- }
- }
+ private class AddBgpVrfWorker implements FutureCallback<List<Void>> {
+ VpnAfConfig config;
+ String vpnName;
- try {
- bgpManager.addVrf(rd, irtList, ertList);
- } catch(Exception e) {
- LOG.error("Exception when adding VRF to BGP", e);
- }
+ public AddBgpVrfWorker(VpnAfConfig config, String vpnName) {
+ this.config = config;
+ this.vpnName = vpnName;
}
- //Try to add up vpn Interfaces if already in Operational Datastore
- InstanceIdentifier<VpnInterfaces> vpnInterfacesId = InstanceIdentifier.builder(VpnInterfaces.class).build();
- Optional<VpnInterfaces> optionalVpnInterfaces = read(LogicalDatastoreType.CONFIGURATION, vpnInterfacesId);
-
- if(optionalVpnInterfaces.isPresent()) {
- List<VpnInterface> vpnInterfaces = optionalVpnInterfaces.get().getVpnInterface();
- for(VpnInterface vpnInterface : vpnInterfaces) {
- if(vpnInterface.getVpnInstanceName().equals(vpnInstanceName)) {
- LOG.debug("VpnInterface {} will be added from VPN {}", vpnInterface.getName(), vpnInstanceName);
- vpnInterfaceManager.add(
- VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
+ /**
+ * @param voids
+ * This implies that all the future instances have returned success. -- TODO: Confirm this
+ */
+ @Override
+ public void onSuccess(List<Void> voids) {
+ String rd = config.getRouteDistinguisher();
+ if (rd != null) {
+ List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
+
+ List<String> ertList = new ArrayList<String>();
+ List<String> irtList = new ArrayList<String>();
+
+ for (VpnTarget vpnTarget : vpnTargetList) {
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
+ ertList.add(vpnTarget.getVrfRTValue());
+ }
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
+ irtList.add(vpnTarget.getVrfRTValue());
+ }
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
+ ertList.add(vpnTarget.getVrfRTValue());
+ irtList.add(vpnTarget.getVrfRTValue());
+ }
+ }
+
+ try {
+ bgpManager.addVrf(rd, irtList, ertList);
+ } catch (Exception e) {
+ LOG.error("Exception when adding VRF to BGP", e);
+ return;
}
+ vpnInterfaceManager.handleVpnsExportingRoutes(this.vpnName, rd);
}
}
- vpnInterfaceManager.handleVpnsExportingRoutes(vpnInstanceName, rd);
+ /**
+ *
+ * @param throwable
+ * This method is used to handle failure callbacks.
+ * If more retry needed, the retrycount is decremented and mainworker is executed again.
+ * After retries completed, rollbackworker is executed.
+ * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
+ */
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ LOG.warn("Job: failed with exception: {}", throwable.getStackTrace());
+ }
}
public boolean isVPNConfigured() {
InterVpnLink interVpnLink = VpnUtil.getInterVpnLinkByEndpointIp(dataBroker, nexthop);
if ( interVpnLink != null ) {
// A static route pointing to an InterVpnLink endpoint: just write the VrfEntry
- VpnUtil.addFibEntryToDS(dataBroker, vpnRd, destination, nexthop, label.intValue(), RouteOrigin.STATIC);
+ VpnUtil.addFibEntryToDS(dataBroker, vpnRd, destination, nexthop, label.intValue(), RouteOrigin.STATIC , null);
} else {
vpnInterfaceMgr.addExtraRoute(destination, nexthop, vpnRd, null /*routerId */, label.intValue(),
null /* intfName */);
InterVpnLink interVpnLink = VpnUtil.getInterVpnLinkByEndpointIp(dataBroker, nexthop);
if ( interVpnLink != null ) {
// A static route pointing to an InterVpnLink endpoint: just remove the VrfEntry from DS
- VpnUtil.removeFibEntryFromDS(dataBroker, vpnRd, destination, nexthop);
+ VpnUtil.removeFibEntryFromDS(dataBroker, vpnRd, destination, nexthop, null);
} else {
vpnInterfaceMgr.delExtraRoute(destination, nexthop, vpnRd, null /*routerId*/, null /*intfName*/);
}
}
}
- public void onInterfaceUp(Interface intfState) {
-
- logger.info("onInterfaceUp: Port " + intfState.getName());
+ public void onInterfaceUp(BigInteger dpnId, String intfName) {
+ logger.info("onInterfaceUp: Port " + intfName);
//TODO(vivek): Change this to use more granularized lock at subnetId level
synchronized (this) {
SubnetToDpn subDpn = null;
- String intfName = intfState.getName();
PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(intfName);
if (portOpEntry == null) {
- logger.info("onInterfaceUp: Port " + intfState.getName() + "is part of a subnet not in VPN, ignoring");
+ logger.info("onInterfaceUp: Port " + intfName + "is part of a subnet not in VPN, ignoring");
return;
}
- BigInteger dpnId = portOpEntry.getDpnId();
- if (dpnId == null) {
- dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
+
+ if ((dpnId == null) || (dpnId == BigInteger.ZERO)) {
+ dpnId = portOpEntry.getDpnId();
if (dpnId == null) {
logger.error("onInterfaceUp: Unable to determine the DPNID for port " + intfName);
return;
}
}
- public void onInterfaceDown(Interface intfState) {
- logger.info("onInterfaceDown: Port " + intfState.getName());
+ public void onInterfaceDown(final BigInteger dpnId, final String interfaceName) {
+ logger.info("onInterfaceDown: Port " + interfaceName);
//TODO(vivek): Change this to use more granularized lock at subnetId level
synchronized (this) {
- String intfName = intfState.getName();
- PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(intfName);
+ PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(interfaceName);
if (portOpEntry == null) {
- logger.info("onInterfaceDown: Port " + intfState.getName() + "is part of a subnet not in VPN, ignoring");
+ logger.info("onInterfaceDown: Port " + interfaceName + "is part of a subnet not in VPN, ignoring");
return;
}
- BigInteger dpnId = portOpEntry.getDpnId();
- if (dpnId == null) {
- dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
- if (dpnId == null) {
- logger.error("onInterfaceDown: Unable to determine the DPNID for port " + intfName);
- return;
- }
+ if ((dpnId == null) ||(dpnId == BigInteger.ZERO)) {
+ logger.error("onInterfaceDown: Unable to determine the DPNID for port " + interfaceName);
+ return;
}
Uuid subnetId = portOpEntry.getSubnetId();
try {
logger.debug("onInterfaceDown: Updating the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
- boolean last = subOpDpnManager.removeInterfaceFromDpn(subnetId, dpnId, intfName);
+ boolean last = subOpDpnManager.removeInterfaceFromDpn(subnetId, dpnId, interfaceName);
InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker,
if ((nhDpnId != null) && (nhDpnId.equals(dpnId))) {
// select another NhDpnId
if (last) {
- logger.debug("onInterfaceDown: Last active port " + intfState.getName() + " on the subnet: " + subnetId.getValue());
+ logger.debug("onInterfaceDown: Last active port " + interfaceName + " on the subnet: " + subnetId.getValue());
// last port on this DPN, so we need to swap the NHDpnId
subDpnList = subOpBuilder.getSubnetToDpn();
if (subDpnList.isEmpty()) {
}
subOpEntry = subOpBuilder.build();
MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
- logger.info("onInterfaceDown: Updated subnetopdataentry to OP Datastore port down " + intfName);
+ logger.info("onInterfaceDown: Updated subnetopdataentry to OP Datastore port down " + interfaceName);
} catch (Exception ex) {
logger.error("Creation of SubnetOpDataEntry for subnet " +
subnetId.getValue() + " failed {}" + ex);
Preconditions.checkNotNull(elanTag, "elanTag cannot be null or empty!");
String nexthopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, nhDpnId);
if(nexthopIp != null)
- vpnInterfaceManager.addSubnetRouteFibEntryToDS(rd, vpnName, subnetIp, nexthopIp, label, elanTag, nhDpnId);
+ vpnInterfaceManager.addSubnetRouteFibEntryToDS(rd, vpnName, subnetIp, nexthopIp, label, elanTag, nhDpnId , null);
else
logger.info("Unable to get nextHop ip address for nextHop DPN {}. Abort adding subnet route to FIB table.", nhDpnId);
}
* @param nextHop Nexthop of the route
* @param label Label of the route
*/
- public static void addFibEntryToDS(DataBroker broker, String rd, String prefix, String nextHop, int label, RouteOrigin origin) {
+ public static void addFibEntryToDS(DataBroker broker, String rd, String prefix, String nextHop, int label,
+ RouteOrigin origin,
+ WriteTransaction writeTxn) {
Preconditions.checkNotNull(rd, "RD cannot be null");
+ VrfEntry vrfEntry = null;
+
LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nextHop, label);
synchronized (rd.intern()) {
InstanceIdentifier<VrfTables> vrfTableId =
InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
- VrfEntry vrfEntry = getVrfEntry(broker, rd, prefix);
+ vrfEntry = getVrfEntry(broker, rd, prefix);
if (vrfEntry != null) {
List<String> nextHopList = vrfEntry.getNextHopAddressList();
nextHopList.add(nextHop);
VrfEntryBuilder builder = new VrfEntryBuilder(vrfEntry).setNextHopAddressList(nextHopList);
VrfEntry newVrfEntry = builder.build();
// Just update the VrfEntry
- VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION,
- vrfTableId.child(VrfEntry.class, new VrfEntryKey(prefix)), newVrfEntry);
+ if (writeTxn != null) {
+ writeTxn.merge(LogicalDatastoreType.CONFIGURATION,
+ vrfTableId.child(VrfEntry.class, new VrfEntryKey(prefix)), newVrfEntry, true);
+ } else {
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION,
+ vrfTableId.child(VrfEntry.class, new VrfEntryKey(prefix)), newVrfEntry);
+ }
} else {
List<VrfEntry> currentVrfEntries = new ArrayList<VrfEntry>();
VrfEntryBuilder builder = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
currentVrfEntries.add(vrfEntry);
VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(
currentVrfEntries).build();
- VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
+ if (writeTxn != null) {
+ writeTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
+ } else {
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
+ }
}
LOG.info("ADD: Added Fib Entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHop, label);
}
* @param nextHopToRemove Specific nexthop within the Route to be removed.
* If null or empty, then the whole VrfEntry is removed
*/
- public static void removeFibEntryFromDS(DataBroker broker, String rd, String prefix, String nextHopToRemove) {
+ public static void removeFibEntryFromDS(DataBroker broker, String rd, String prefix, String nextHopToRemove,
+ WriteTransaction writeTxn) {
LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
if (nhListRead.isEmpty()) {
// Remove the whole entry
- MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+ if (writeTxn != null) {
+ writeTxn.delete(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+ } else {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+ }
LOG.info("Removed Fib Entry rd {} prefix {}", rd, prefix);
} else {
// An update must be done, not including the current next hop
VrfEntry vrfEntry =
- new VrfEntryBuilder(entry.get()).setDestPrefix(prefix).setNextHopAddressList(nhListRead)
- .setKey(new VrfEntryKey(prefix)).build();
- MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
- MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
+ new VrfEntryBuilder(entry.get()).setDestPrefix(prefix).setNextHopAddressList(nhListRead)
+ .setKey(new VrfEntryKey(prefix)).build();
+ if (writeTxn != null) {
+ writeTxn.delete(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+ writeTxn.put(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
+ } else {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
+ }
LOG.info("Removed Nexthop {} from Fib Entry rd {} prefix {}", nextHopToRemove, rd, prefix);
}
}
new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
}
+ static RouterInterface getConfiguredRouterInterface(DataBroker broker, String interfaceName) {
+ Optional<RouterInterface> optRouterInterface = read(broker, LogicalDatastoreType.CONFIGURATION, VpnUtil.getRouterInterfaceId(interfaceName));
+ if(optRouterInterface.isPresent()) {
+ return optRouterInterface.get();
+ }
+ return null;
+ }
+
static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds
getVpnIdToVpnInstance(long vpnId, String vpnName, String rd, boolean isExternalVpn) {
return new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsBuilder()
// DPN has gone down (and the VpnToDpnMap has been removed in a different Thread)
}
- public static void removePrefixToInterfaceForVpnId(DataBroker broker, long vpnId) {
+ public static void removePrefixToInterfaceForVpnId(DataBroker broker, long vpnId, WriteTransaction writeTxn) {
try {
// Clean up PrefixToInterface Operational DS
- delete(broker, LogicalDatastoreType.OPERATIONAL,
- InstanceIdentifier.builder(PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId)).build(),
- DEFAULT_CALLBACK);
+ if (writeTxn != null) {
+ writeTxn.delete(LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(PrefixToInterface.class).child(
+ VpnIds.class, new VpnIdsKey(vpnId)).build());
+ } else {
+ delete(broker, LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId)).build(),
+ DEFAULT_CALLBACK);
+ }
} catch (Exception e) {
LOG.error("Exception during cleanup of PrefixToInterface for VPN ID {}", vpnId, e);
}
}
- public static void removeVpnExtraRouteForVpn(DataBroker broker, String vpnName) {
+ public static void removeVpnExtraRouteForVpn(DataBroker broker, String vpnName, WriteTransaction writeTxn) {
try {
// Clean up VPNExtraRoutes Operational DS
- delete(broker, LogicalDatastoreType.OPERATIONAL,
- InstanceIdentifier.builder(VpnToExtraroute.class).child(Vpn.class, new VpnKey(vpnName)).build(),
- DEFAULT_CALLBACK);
+ if (writeTxn != null) {
+ writeTxn.delete(LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(VpnToExtraroute.class).child(Vpn.class, new VpnKey(vpnName)).build());
+ } else {
+ delete(broker, LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(VpnToExtraroute.class).child(Vpn.class, new VpnKey(vpnName)).build(),
+ DEFAULT_CALLBACK);
+ }
} catch (Exception e) {
LOG.error("Exception during cleanup of VPNToExtraRoute for VPN {}", vpnName, e);
}
}
- public static void removeVpnOpInstance(DataBroker broker, String vpnName) {
+ public static void removeVpnOpInstance(DataBroker broker, String vpnName, WriteTransaction writeTxn) {
try {
// Clean up VPNInstanceOpDataEntry
- delete(broker, LogicalDatastoreType.OPERATIONAL, getVpnInstanceOpDataIdentifier(vpnName),
- DEFAULT_CALLBACK);
+ if (writeTxn != null) {
+ writeTxn.delete(LogicalDatastoreType.OPERATIONAL, getVpnInstanceOpDataIdentifier(vpnName));
+ } else {
+ delete(broker, LogicalDatastoreType.OPERATIONAL, getVpnInstanceOpDataIdentifier(vpnName),
+ DEFAULT_CALLBACK);
+ }
} catch (Exception e) {
LOG.error("Exception during cleanup of VPNInstanceOpDataEntry for VPN {}", vpnName, e);
}
}
- public static void removeVpnInstanceToVpnId(DataBroker broker, String vpnName) {
+ public static void removeVpnInstanceToVpnId(DataBroker broker, String vpnName, WriteTransaction writeTxn) {
try {
- delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnInstanceToVpnIdIdentifier(vpnName),
- DEFAULT_CALLBACK);
+ if (writeTxn != null) {
+ writeTxn.delete(LogicalDatastoreType.CONFIGURATION, getVpnInstanceToVpnIdIdentifier(vpnName));
+ } else {
+ delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnInstanceToVpnIdIdentifier(vpnName),
+ DEFAULT_CALLBACK);
+ }
} catch (Exception e) {
LOG.error("Exception during clean up of VpnInstanceToVpnId for VPN {}", vpnName, e);
}
}
- public static void removeVpnIdToVpnInstance(DataBroker broker, long vpnId) {
+ public static void removeVpnIdToVpnInstance(DataBroker broker, long vpnId, WriteTransaction writeTxn) {
try {
- delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnIdToVpnInstanceIdentifier(vpnId),
- DEFAULT_CALLBACK);
+ if (writeTxn != null) {
+ writeTxn.delete(LogicalDatastoreType.CONFIGURATION, getVpnIdToVpnInstanceIdentifier(vpnId));
+ } else {
+ delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnIdToVpnInstanceIdentifier(vpnId),
+ DEFAULT_CALLBACK);
+ }
} catch (Exception e) {
LOG.error("Exception during clean up of VpnIdToVpnInstance for VPNID {}", vpnId, e);
}
}
- public static void removeVrfTableForVpn(DataBroker broker, String vpnName) {
+ public static void removeVrfTableForVpn(DataBroker broker, String vpnName, WriteTransaction writeTxn) {
// Clean up FIB Entries Config DS
try {
- delete(broker, LogicalDatastoreType.CONFIGURATION,
- InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(vpnName)).build(),
- DEFAULT_CALLBACK);
+ if (writeTxn != null) {
+ writeTxn.delete(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(vpnName)).build());
+ } else {
+ delete(broker, LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(vpnName)).build(),
+ DEFAULT_CALLBACK);
+ }
} catch (Exception e) {
LOG.error("Exception during clean up of VrfTable from FIB for VPN {}", vpnName, e);
}
}
- public static void removeL3nexthopForVpnId(DataBroker broker, long vpnId) {
+ public static void removeL3nexthopForVpnId(DataBroker broker, long vpnId, WriteTransaction writeTxn) {
try {
// Clean up L3NextHop Operational DS
- delete(broker, LogicalDatastoreType.OPERATIONAL,
- InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).build(),
- DEFAULT_CALLBACK);
+ if (writeTxn != null) {
+ writeTxn.delete(LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).build());
+ } else {
+ delete(broker, LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).build(),
+ DEFAULT_CALLBACK);
+ }
} catch (Exception e) {
LOG.error("Exception during cleanup of L3NextHop for VPN ID {}", vpnId, e);
}
return result;
}
- public static void updateVpnInterface(DataBroker broker,String interfaceName, BigInteger dpnId, String vpnInstanceName, Boolean isScheduledToRemove){
+ public static void updateVpnInterface(DataBroker broker,String interfaceName, BigInteger dpnId,
+ String vpnInstanceName, Boolean isScheduledToRemove,
+ WriteTransaction writeTxn){
InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
VpnInterface interfaceToUpdate = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(interfaceName)).setName(interfaceName)
.setDpnId(dpnId).setVpnInstanceName(vpnInstanceName).setScheduledForRemove(isScheduledToRemove).build();
- VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate);
+ writeTxn.merge(LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate, true);
+ //VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate);
}
protected static void createVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp,
@Test
public void testOnInterfaceUp() {
- vpnSubnetRouteHandler.onInterfaceUp(stateInterface);
+ vpnSubnetRouteHandler.onInterfaceUp(dpId, interfaceName);
verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, instPortOp, portOp, true);
verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, dpnOpId, subnetToDpn, true);
@Test
public void testOnInterfaceDown() {
- vpnSubnetRouteHandler.onInterfaceDown(stateInterface);
+ vpnSubnetRouteHandler.onInterfaceDown(dpId, interfaceName);
verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, dpnOpId);
verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subnetOp, true);