/*
- * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ * Copyright (c) 2015 - 2017 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,
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+
+import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.mdsalutil.FlowEntity;
+import org.opendaylight.genius.mdsalutil.InstructionInfo;
+import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.genius.mdsalutil.MatchInfo;
+import org.opendaylight.genius.mdsalutil.MetaDataUtil;
+import org.opendaylight.genius.mdsalutil.NWUtil;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
+import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
import org.opendaylight.netvirt.fibmanager.api.IFibManager;
+import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.LayerType;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
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.instances.VpnInstance;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIp;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
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.VpnTargetsBuilder;
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.vpntargets.VpnTargetBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTargetKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.Vpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.Vpn;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class VpnInstanceListener extends AsyncDataTreeChangeListenerBase<VpnInstance, VpnInstanceListener>
- implements AutoCloseable {
+ implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(VpnInstanceListener.class);
private final DataBroker dataBroker;
private final IBgpManager bgpManager;
private final VpnInterfaceManager vpnInterfaceManager;
private final IFibManager fibManager;
private final VpnOpDataSyncer vpnOpDataNotifier;
+ private final IMdsalApiManager mdsalManager;
public VpnInstanceListener(final DataBroker dataBroker, final IBgpManager bgpManager,
- final IdManagerService idManager,
- final VpnInterfaceManager vpnInterfaceManager,
- final IFibManager fibManager,
- final VpnOpDataSyncer vpnOpDataSyncer) {
+ final IdManagerService idManager, final VpnInterfaceManager vpnInterfaceManager, final IFibManager fibManager,
+ final VpnOpDataSyncer vpnOpDataSyncer, final IMdsalApiManager mdsalManager) {
super(VpnInstance.class, VpnInstanceListener.class);
this.dataBroker = dataBroker;
this.bgpManager = bgpManager;
this.vpnInterfaceManager = vpnInterfaceManager;
this.fibManager = fibManager;
this.vpnOpDataNotifier = vpnOpDataSyncer;
+ this.mdsalManager = mdsalManager;
}
public void start() {
}
private void waitForOpRemoval(String rd, String vpnName) {
- //wait till DCN for update on VPN Instance Op Data signals that vpn interfaces linked to this vpn instance is zero
+ //wait till DCN for update on VPN Instance Op Data signals that vpn interfaces linked to this vpn instance is
+ // zero
//TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
VpnInstanceOpDataEntry vpnOpEntry = null;
Long intfCount = 0L;
long timeout = VpnConstants.MIN_WAIT_TIME_IN_MILLISECONDS;
Optional<VpnInstanceOpDataEntry> vpnOpValue = null;
vpnOpValue = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
- VpnUtil.getVpnInstanceOpDataIdentifier(rd));
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd));
if ((vpnOpValue != null) && (vpnOpValue.isPresent())) {
vpnOpEntry = vpnOpValue.get();
timeout = VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS;
}
LOG.info("VPNInstance removal count of interface at {} for for rd {}, vpnname {}",
- intfCount, rd, vpnName);
+ intfCount, rd, vpnName);
}
LOG.info("VPNInstance removal thread waiting for {} seconds for rd {}, vpnname {}",
- (timeout / 1000), rd, vpnName);
+ (timeout / 1000), rd, vpnName);
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
+ // Ignored
}
// Check current interface count
vpnOpValue = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
- VpnUtil.getVpnInstanceOpDataIdentifier(rd));
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd));
if ((vpnOpValue != null) && (vpnOpValue.isPresent())) {
vpnOpEntry = vpnOpValue.get();
dpnToVpns = vpnOpEntry.getVpnToDpnList();
} else {
if (retryCount > 0) {
retryCount--;
- LOG.info("Retrying clearing vpn with vpnname {} rd {} since current interface count {} ", vpnName, rd, currentIntfCount);
+ LOG.info(
+ "Retrying clearing vpn with vpnname {} rd {} since current interface count {} ",
+ vpnName, rd, currentIntfCount);
if (currentIntfCount > 0) {
intfCount = currentIntfCount;
} else {
- LOG.info("Current interface count is zero, but instance Op for vpn {} and rd {} not cleared yet. Waiting for 5 more seconds.", vpnName, rd);
+ LOG.info(
+ "Current interface count is zero, but instance Op for vpn {} and rd {} not "
+ + "cleared yet. Waiting for 5 more seconds.",
+ vpnName, rd);
intfCount = 1L;
}
} else {
- LOG.info("VPNInstance bailing out of wait loop as current interface count is {} and max retries exceeded for for vpnName {}, rd {}",
- currentIntfCount, vpnName, rd);
+ LOG.info(
+ "VPNInstance bailing out of wait loop as current interface count is {} and max "
+ + "retries exceeded for for vpnName {}, rd {}",
+ currentIntfCount, vpnName, rd);
break;
}
}
// There is no VPNOPEntry. Something else happened on the system !
// So let us quit and take our chances.
//TODO(vpnteam): L3VPN refactoring to take care of this case.
- LOG.error("VpnInstanceOpData is not present in the operational DS for rd {}, vpnname {}", rd, vpnName);
+ LOG.error("VpnInstanceOpData is not present in the operational DS for rd {}, vpnname {}", rd,
+ vpnName);
break;
}
}
}
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);
final String vpnName = del.getVpnInstanceName();
- final String rd = del.getIpv4Family().getRouteDistinguisher();
Optional<VpnInstanceOpDataEntry> vpnOpValue = null;
+ String primaryRd = VpnUtil.getPrimaryRd(del);
//TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
try {
- if ((rd != null) && (!rd.isEmpty())) {
- vpnOpValue = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
- VpnUtil.getVpnInstanceOpDataIdentifier(rd));
- } else {
- vpnOpValue = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
- VpnUtil.getVpnInstanceOpDataIdentifier(vpnName));
- }
- } catch (Exception e) {
+ vpnOpValue = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd));
+ } catch (ReadFailedException e) {
LOG.error("Exception when attempting to retrieve VpnInstanceOpDataEntry for VPN {}. ", vpnName, e);
return;
}
DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
dataStoreCoordinator.enqueueJob("VPN-" + vpnName,
- new DeleteVpnInstanceWorker(idManager, dataBroker, del));
+ new DeleteVpnInstanceWorker(idManager, dataBroker, del));
}
private class DeleteVpnInstanceWorker implements Callable<List<ListenableFuture<Void>>> {
DataBroker broker;
VpnInstance vpnInstance;
- public DeleteVpnInstanceWorker(IdManagerService idManager,
- DataBroker broker,
- VpnInstance value) {
+ DeleteVpnInstanceWorker(IdManagerService idManager,
+ DataBroker broker,
+ VpnInstance value) {
this.idManager = idManager;
this.broker = broker;
this.vpnInstance = value;
}
@Override
- public List<ListenableFuture<Void>> call() throws Exception {
+ public List<ListenableFuture<Void>> call() {
final String vpnName = vpnInstance.getVpnInstanceName();
- final String rd = vpnInstance.getIpv4Family().getRouteDistinguisher();
+ final List<String> rds = vpnInstance.getIpv4Family().getRouteDistinguisher();
+ String primaryRd = VpnUtil.getPrimaryRd(vpnInstance);
final long vpnId = VpnUtil.getVpnId(broker, vpnName);
WriteTransaction writeTxn = broker.newWriteOnlyTransaction();
- if ((rd != null) && (!rd.isEmpty())) {
- waitForOpRemoval(rd, vpnName);
- } else {
- waitForOpRemoval(vpnName, vpnName);
- }
+ waitForOpRemoval(primaryRd, vpnName);
// Clean up VpnInstanceToVpnId from Config DS
VpnUtil.removeVpnIdToVpnInstance(broker, vpnId, writeTxn);
VpnUtil.removeVpnInstanceToVpnId(broker, vpnName, writeTxn);
- LOG.trace("Removed vpnIdentifier for rd{} vpnname {}", rd, vpnName);
- if (rd != null) {
- synchronized (vpnName.intern()) {
- fibManager.removeVrfTable(broker, rd, null);
- }
- try {
- bgpManager.deleteVrf(rd, false);
- } catch (Exception e) {
- LOG.error("Exception when removing VRF from BGP for RD {} in VPN {} exception " + e, rd, vpnName);
- }
-
- // Clean up VPNExtraRoutes Operational DS
- InstanceIdentifier<Vpn> vpnToExtraroute = VpnUtil.getVpnToExtrarouteIdentifier(rd);
- Optional<Vpn> optVpnToExtraroute = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, vpnToExtraroute);
- if (optVpnToExtraroute.isPresent()) {
- VpnUtil.removeVpnExtraRouteForVpn(broker, rd, writeTxn);
- }
-
- // Clean up VPNInstanceOpDataEntry
- VpnUtil.removeVpnOpInstance(broker, rd, writeTxn);
- } else {
- // Clean up FIB Entries Config DS
- synchronized (vpnName.intern()) {
- fibManager.removeVrfTable(broker, vpnName, null);
- }
- // Clean up VPNExtraRoutes Operational DS
- InstanceIdentifier<Vpn> vpnToExtraroute = VpnUtil.getVpnToExtrarouteIdentifier(vpnName);
- Optional<Vpn> optVpnToExtraroute = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, vpnToExtraroute);
- if (optVpnToExtraroute.isPresent()) {
- VpnUtil.removeVpnExtraRouteForVpn(broker, vpnName, writeTxn);
- }
+ LOG.trace("Removed vpnIdentifier for rd{} vpnname {}", primaryRd, vpnName);
+ // Clean up FIB Entries Config DS
+ synchronized (vpnName.intern()) {
+ fibManager.removeVrfTable(broker, primaryRd, null);
+ }
+ if (VpnUtil.isBgpVpn(vpnName, primaryRd)) {
+ rds.parallelStream().forEach(rd -> bgpManager.deleteVrf(rd, false));
+ }
+ // Clean up VPNExtraRoutes Operational DS
+ InstanceIdentifier<Vpn> vpnToExtraroute = VpnExtraRouteHelper.getVpnToExtrarouteVpnIdentifier(vpnName);
+ Optional<Vpn> optVpnToExtraroute = VpnUtil.read(broker,
+ LogicalDatastoreType.OPERATIONAL, vpnToExtraroute);
+ if (optVpnToExtraroute.isPresent()) {
+ VpnUtil.removeVpnExtraRouteForVpn(broker, vpnName, writeTxn);
+ }
- // Clean up VPNInstanceOpDataEntry
- VpnUtil.removeVpnOpInstance(broker, vpnName, writeTxn);
+ if (VpnUtil.isL3VpnOverVxLan(vpnInstance.getL3vni())) {
+ removeExternalTunnelDemuxFlows(vpnName);
}
+
+ // Clean up VPNInstanceOpDataEntry
+ VpnUtil.removeVpnOpInstance(broker, primaryRd, writeTxn);
// Clean up PrefixToInterface Operational DS
VpnUtil.removePrefixToInterfaceForVpnId(broker, vpnId, writeTxn);
@Override
protected void update(InstanceIdentifier<VpnInstance> identifier,
- VpnInstance original, VpnInstance update) {
+ VpnInstance original, VpnInstance update) {
LOG.trace("Update VPN event key: {}, value: {}", identifier, update);
}
DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
dataStoreCoordinator.enqueueJob("VPN-" + vpnName,
- new AddVpnInstanceWorker(idManager, vpnInterfaceManager, dataBroker, value));
+ new AddVpnInstanceWorker(idManager, vpnInterfaceManager, dataBroker, value));
}
private class AddVpnInstanceWorker implements Callable<List<ListenableFuture<Void>>> {
VpnInstance vpnInstance;
DataBroker broker;
- public AddVpnInstanceWorker(IdManagerService idManager,
- VpnInterfaceManager vpnInterfaceManager,
- DataBroker broker,
- VpnInstance value) {
+ AddVpnInstanceWorker(IdManagerService idManager,
+ VpnInterfaceManager vpnInterfaceManager,
+ DataBroker broker,
+ VpnInstance value) {
this.idManager = idManager;
this.vpnInterfaceManager = vpnInterfaceManager;
this.broker = broker;
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();
WriteTransaction writeConfigTxn = broker.newWriteOnlyTransaction();
WriteTransaction writeOperTxn = broker.newWriteOnlyTransaction();
addVpnInstance(vpnInstance, writeConfigTxn, writeOperTxn);
futures.add(writeConfigTxn.submit());
ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
Futures.addCallback(listenableFuture,
- new PostAddVpnInstanceWorker(config , vpnInstance.getVpnInstanceName()));
+ new PostAddVpnInstanceWorker(vpnInstance , vpnInstance.getVpnInstanceName()));
return futures;
}
}
+ // TODO Clean up the exception handling
+ @SuppressWarnings("checkstyle:IllegalCatch")
private void addVpnInstance(VpnInstance value, WriteTransaction writeConfigTxn,
- WriteTransaction writeOperTxn) {
+ WriteTransaction writeOperTxn) {
VpnAfConfig config = value.getIpv4Family();
- String rd = config.getRouteDistinguisher();
String vpnInstanceName = value.getVpnInstanceName();
long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnInstanceName);
if (vpnId == 0) {
- LOG.error("Unable to fetch label from Id Manager. Bailing out of adding operational data for Vpn Instance {}", value.getVpnInstanceName());
- LOG.error("Unable to fetch label from Id Manager. Bailing out of adding operational data for Vpn Instance {}", value.getVpnInstanceName());
+ LOG.error(
+ "Unable to fetch label from Id Manager. Bailing out of adding operational data for Vpn Instance {}",
+ value.getVpnInstanceName());
+ LOG.error(
+ "Unable to fetch label from Id Manager. Bailing out of adding operational data for Vpn Instance {}",
+ value.getVpnInstanceName());
return;
}
LOG.info("VPN Id {} generated for VpnInstanceName {}", vpnId, vpnInstanceName);
+ String primaryRd = VpnUtil.getPrimaryRd(value);
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, primaryRd);
if (writeConfigTxn != null) {
writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION,
- VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
- vpnInstanceToVpnId, true);
+ VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
+ vpnInstanceToVpnId, true);
} else {
- TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
- VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
- vpnInstanceToVpnId, TransactionUtil.DEFAULT_CALLBACK);
+ TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
+ VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
+ vpnInstanceToVpnId, TransactionUtil.DEFAULT_CALLBACK);
}
VpnIds vpnIdToVpnInstance = VpnUtil.getVpnIdToVpnInstance(vpnId, value.getVpnInstanceName(),
- (rd != null) ? rd : value.getVpnInstanceName(), (rd != null)/*isExternalVpn*/);
+ primaryRd, VpnUtil.isBgpVpn(vpnInstanceName, primaryRd));
if (writeConfigTxn != null) {
writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION,
- VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
- vpnIdToVpnInstance, true);
+ VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
+ vpnIdToVpnInstance, true);
} else {
- TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
- VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
- vpnIdToVpnInstance, TransactionUtil.DEFAULT_CALLBACK);
+ TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
+ VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
+ vpnIdToVpnInstance, TransactionUtil.DEFAULT_CALLBACK);
}
try {
LOG.error("Error when trying to retrieve tunnel transport type for L3VPN ", e);
}
- if (rd == null) {
- VpnInstanceOpDataEntryBuilder builder =
- new VpnInstanceOpDataEntryBuilder().setVrfId(vpnInstanceName).setVpnId(vpnId)
- .setVpnInstanceName(vpnInstanceName);
- if (writeOperTxn != null) {
- writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
- VpnUtil.getVpnInstanceOpDataIdentifier(vpnInstanceName),
- builder.build(), true);
- } else {
- TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
- VpnUtil.getVpnInstanceOpDataIdentifier(vpnInstanceName),
- builder.build(), TransactionUtil.DEFAULT_CALLBACK);
+ VpnInstanceOpDataEntryBuilder builder =
+ new VpnInstanceOpDataEntryBuilder().setVrfId(primaryRd).setVpnId(vpnId)
+ .setVpnInstanceName(vpnInstanceName);
+ if (VpnUtil.isBgpVpn(vpnInstanceName, primaryRd)) {
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn
+ .instance.op.data.entry.vpntargets.VpnTarget> opVpnTargetList = new ArrayList<>();
+ if (value.getL3vni() != null) {
+ builder.setL3vni(value.getL3vni());
}
- } else {
- VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder()
- .setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnInstanceName);
-
- List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget> opVpnTargetList = new ArrayList<>();
VpnTargets vpnTargets = config.getVpnTargets();
if (vpnTargets != null) {
List<VpnTarget> vpnTargetList = vpnTargets.getVpnTarget();
if (vpnTargetList != null) {
for (VpnTarget vpnTarget : vpnTargetList) {
- VpnTargetBuilder vpnTargetBuilder = new VpnTargetBuilder().setKey(new VpnTargetKey(vpnTarget.getKey().getVrfRTValue()))
- .setVrfRTType(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
- .instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget.VrfRTType
- .forValue(vpnTarget.getVrfRTType().getIntValue())).setVrfRTValue(vpnTarget.getVrfRTValue());
+ VpnTargetBuilder vpnTargetBuilder =
+ new VpnTargetBuilder().setKey(new VpnTargetKey(vpnTarget.getKey().getVrfRTValue()))
+ .setVrfRTType(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
+ .instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget.VrfRTType
+ .forValue(vpnTarget.getVrfRTType().getIntValue())).setVrfRTValue(
+ vpnTarget.getVrfRTValue());
opVpnTargetList.add(vpnTargetBuilder.build());
}
}
}
VpnTargetsBuilder vpnTargetsBuilder = new VpnTargetsBuilder().setVpnTarget(opVpnTargetList);
builder.setVpnTargets(vpnTargetsBuilder.build());
-
- if (writeOperTxn != null) {
- writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
- VpnUtil.getVpnInstanceOpDataIdentifier(rd),
- builder.build(), true);
- } else {
- TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
- VpnUtil.getVpnInstanceOpDataIdentifier(rd),
- builder.build(), TransactionUtil.DEFAULT_CALLBACK);
- }
}
- LOG.info("VpnInstanceOpData populated successfully for vpn {} rd {}", vpnInstanceName, rd);
+ if (writeOperTxn != null) {
+ writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd),
+ builder.build(), true);
+ } else {
+ TransactionUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(primaryRd),
+ builder.build(), TransactionUtil.DEFAULT_CALLBACK);
+ }
+ LOG.info("VpnInstanceOpData populated successfully for vpn {} rd {}", vpnInstanceName, primaryRd);
}
-
private class PostAddVpnInstanceWorker implements FutureCallback<List<Void>> {
- VpnAfConfig config;
+ VpnInstance vpnInstance;
String vpnName;
- public PostAddVpnInstanceWorker(VpnAfConfig config, String vpnName) {
- this.config = config;
+ PostAddVpnInstanceWorker(VpnInstance vpnInstance, String vpnName) {
+ this.vpnInstance = vpnInstance;
this.vpnName = vpnName;
}
/**
- * @param voids
* This implies that all the future instances have returned success. -- TODO: Confirm this
*/
@Override
if rd is null, then its either a router vpn instance (or) a vlan external network vpn instance.
if rd is non-null, then it is a bgpvpn instance
*/
- String rd = config.getRouteDistinguisher();
+ VpnAfConfig config = vpnInstance.getIpv4Family();
+ List<String> rd = config.getRouteDistinguisher();
if ((rd == null) || addBgpVrf(voids)) {
notifyTask();
vpnInterfaceManager.vpnInstanceIsReady(vpnName);
}
+ VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker,
+ VpnUtil.getPrimaryRd(vpnInstance));
+
+ // bind service on each tunnel interface
+ //TODO (KIRAN): Add a new listener to handle creation of new DC-GW binding and deletion of existing DC-GW.
+ if (VpnUtil.isL3VpnOverVxLan(vpnInstance.getL3vni())) { //Handled for L3VPN Over VxLAN
+ for (String tunnelInterfaceName: getDcGatewayTunnelInterfaceNameList()) {
+ VpnUtil.bindService(vpnInstance.getVpnInstanceName(), tunnelInterfaceName, dataBroker,
+ true/*isTunnelInterface*/);
+ }
+
+ // install flow
+ List<MatchInfo> mkMatches = new ArrayList<>();
+ mkMatches.add(new MatchTunnelId(BigInteger.valueOf(vpnInstance.getL3vni())));
+
+ List<InstructionInfo> instructions =
+ Arrays.asList(new InstructionWriteMetadata(MetaDataUtil.getVpnIdMetadata(vpnInstanceOpDataEntry
+ .getVpnId()), MetaDataUtil.METADATA_MASK_VRFID),
+ new InstructionGotoTable(NwConstants.L3_GW_MAC_TABLE));
+
+ for (BigInteger dpnId: NWUtil.getOperativeDPNs(dataBroker)) {
+ String flowRef = getFibFlowRef(dpnId, NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE,
+ vpnName, VpnConstants.DEFAULT_FLOW_PRIORITY);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId,
+ NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE, flowRef, VpnConstants.DEFAULT_FLOW_PRIORITY,
+ "VxLAN VPN Tunnel Bind Service", 0, 0, NwConstants.COOKIE_VM_FIB_TABLE,
+ mkMatches, instructions);
+ mdsalManager.installFlow(dpnId, flowEntity);
+ }
+
+ ///////////////////////
+ }
}
+ // TODO Clean up the exception handling
+ @SuppressWarnings("checkstyle:IllegalCatch")
private boolean addBgpVrf(List<Void> voids) {
- String rd = config.getRouteDistinguisher();
+ VpnAfConfig config = vpnInstance.getIpv4Family();
+ List<String> rds = config.getRouteDistinguisher();
+ String primaryRd = VpnUtil.getPrimaryRd(dataBroker, vpnName);
List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
- List<String> ertList = new ArrayList<String>();
- List<String> irtList = new ArrayList<String>();
+ List<String> ertList = new ArrayList<>();
+ List<String> irtList = new ArrayList<>();
if (vpnTargetList != null) {
for (VpnTarget vpnTarget : vpnTargetList) {
}
}
} else {
- LOG.error("vpn target list is empty, cannot add BGP VPN {} VRF {}", this.vpnName, rd);
+ LOG.error("vpn target list is empty, cannot add BGP VPN {} VRF {}", this.vpnName, primaryRd);
return false;
}
- try {
- bgpManager.addVrf(rd, irtList, ertList);
- } catch (Exception e) {
- LOG.error("Exception when adding VRF to BGP", e);
+ //Advertise all the rds and check if primary Rd advertisement fails
+ long primaryRdAddFailed = rds.parallelStream().filter(rd -> {
+ try {
+ bgpManager.addVrf(rd, irtList, ertList, LayerType.LAYER3);
+ } catch (Exception e) {
+ LOG.error("Exception when adding VRF {} to BGP {}. Exception {}", rd, vpnName, e);
+ return rd.equals(primaryRd);
+ }
+ return false;
+ }).count();
+ if (primaryRdAddFailed == 1) {
return false;
}
- vpnInterfaceManager.handleVpnsExportingRoutes(this.vpnName, rd);
+ vpnInterfaceManager.handleVpnsExportingRoutes(this.vpnName, primaryRd);
return true;
}
}
/**
- *
- * @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.
InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class).build();
Optional<VpnInstances> optionalVpns = TransactionUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
- vpnsIdentifier);
- if (!optionalVpns.isPresent() ||
- optionalVpns.get().getVpnInstance() == null ||
- optionalVpns.get().getVpnInstance().isEmpty()) {
+ vpnsIdentifier);
+ if (!optionalVpns.isPresent()
+ || optionalVpns.get().getVpnInstance() == null
+ || optionalVpns.get().getVpnInstance().isEmpty()) {
LOG.trace("No VPNs configured.");
return false;
}
protected VpnInstanceOpDataEntry getVpnInstanceOpData(String rd) {
InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
Optional<VpnInstanceOpDataEntry> vpnInstanceOpData =
- TransactionUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
- if(vpnInstanceOpData.isPresent()) {
+ TransactionUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+ if (vpnInstanceOpData.isPresent()) {
return vpnInstanceOpData.get();
}
return null;
}
+
+ private List<String> getDcGatewayTunnelInterfaceNameList() {
+ List<String> tunnelInterfaceNameList = new ArrayList<>();
+
+ InstanceIdentifier<DcGatewayIpList> dcGatewayIpListInstanceIdentifier = InstanceIdentifier
+ .create(DcGatewayIpList.class);
+ Optional<DcGatewayIpList> dcGatewayIpListOptional = VpnUtil.read(dataBroker,
+ LogicalDatastoreType.CONFIGURATION, dcGatewayIpListInstanceIdentifier);
+ if (!dcGatewayIpListOptional.isPresent()) {
+ LOG.info("No DC gateways configured.");
+ return tunnelInterfaceNameList;
+ }
+ List<DcGatewayIp> dcGatewayIps = dcGatewayIpListOptional.get().getDcGatewayIp();
+
+ InstanceIdentifier<ExternalTunnelList> externalTunnelListId = InstanceIdentifier
+ .create(ExternalTunnelList.class);
+
+ Optional<ExternalTunnelList> externalTunnelListOptional = VpnUtil.read(dataBroker,
+ LogicalDatastoreType.OPERATIONAL, externalTunnelListId);
+ if (externalTunnelListOptional.isPresent()) {
+ List<ExternalTunnel> externalTunnels = externalTunnelListOptional.get().getExternalTunnel();
+
+ List<String> externalTunnelIpList = new ArrayList<>();
+ for (ExternalTunnel externalTunnel: externalTunnels) {
+ externalTunnelIpList.add(externalTunnel.getDestinationDevice());
+ }
+
+ List<String> dcGatewayIpList = new ArrayList<>();
+ for (DcGatewayIp dcGatewayIp: dcGatewayIps) {
+ dcGatewayIpList.add(dcGatewayIp.getIpAddress().getIpv4Address().toString());
+ }
+
+ // Find all externalTunnelIps present in dcGateWayIpList
+ List<String> externalTunnelIpsInDcGatewayIpList = new ArrayList<>();
+ for (String externalTunnelIp: externalTunnelIpList) {
+ for (String dcGateWayIp: dcGatewayIpList) {
+ if (externalTunnelIp.contentEquals(dcGateWayIp)) {
+ externalTunnelIpsInDcGatewayIpList.add(externalTunnelIp);
+ }
+ }
+ }
+
+
+ for (String externalTunnelIpsInDcGatewayIp: externalTunnelIpsInDcGatewayIpList) {
+ for (ExternalTunnel externalTunnel: externalTunnels) {
+ if (externalTunnel.getDestinationDevice().contentEquals(externalTunnelIpsInDcGatewayIp)) {
+ tunnelInterfaceNameList.add(externalTunnel.getTunnelInterfaceName());
+ }
+ }
+ }
+
+ }
+
+ return tunnelInterfaceNameList;
+ }
+
+ private String getFibFlowRef(BigInteger dpnId, short tableId, String vpnName, int priority) {
+ return VpnConstants.FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId
+ + NwConstants.FLOWID_SEPARATOR + vpnName + NwConstants.FLOWID_SEPARATOR + priority;
+ }
+
+ private void removeExternalTunnelDemuxFlows(String vpnName) {
+ LOG.info("Removing external tunnel flows for vpn {}", vpnName);
+ for (BigInteger dpnId: NWUtil.getOperativeDPNs(dataBroker)) {
+ LOG.debug("Removing external tunnel flows for vpn {} from dpn {}", vpnName, dpnId);
+ String flowRef = getFibFlowRef(dpnId, NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE,
+ vpnName, VpnConstants.DEFAULT_FLOW_PRIORITY);
+ FlowEntity flowEntity = VpnUtil.buildFlowEntity(dpnId,
+ NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE, flowRef);
+ mdsalManager.removeFlow(flowEntity);
+ }
+ }
}