*/
package org.opendaylight.netvirt.vpnmanager;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.HashMap;
-
-import com.google.common.base.Preconditions;
-
-import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PortOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.SubnetOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.TaskState;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.*;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpn;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfaces;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.PortAddedToSubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.PortRemovedFromSubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterAssociatedToVpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterDisassociatedFromVpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetAddedToVpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetAddedToVpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetDeletedFromVpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetDeletedFromVpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetUpdatedInVpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import java.math.BigInteger;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-
-
public class VpnSubnetRouteHandler implements NeutronvpnListener {
private static final Logger logger = LoggerFactory.getLogger(VpnSubnetRouteHandler.class);
-
- private final DataBroker broker;
- private SubnetOpDpnManager subOpDpnManager;
+ private final DataBroker dataBroker;
+ private final SubnetOpDpnManager subOpDpnManager;
private final IBgpManager bgpManager;
- private IdManagerService idManager;
- private VpnInterfaceManager vpnInterfaceManager;
-
- public VpnSubnetRouteHandler(final DataBroker db, IBgpManager bgpManager, VpnInterfaceManager vpnIntfManager) {
- broker = db;
- subOpDpnManager = new SubnetOpDpnManager(broker);
+ private final VpnInterfaceManager vpnInterfaceManager;
+ private final IdManagerService idManager;
+ private LockManagerService lockManager;
+
+ public VpnSubnetRouteHandler(final DataBroker dataBroker, final SubnetOpDpnManager subnetOpDpnManager,
+ final IBgpManager bgpManager, final VpnInterfaceManager vpnIntfManager,
+ final IdManagerService idManager, LockManagerService lockManagerService) {
+ this.dataBroker = dataBroker;
+ this.subOpDpnManager = subnetOpDpnManager;
this.bgpManager = bgpManager;
this.vpnInterfaceManager = vpnIntfManager;
- }
-
- public void setIdManager(IdManagerService idManager) {
this.idManager = idManager;
+ this.lockManager = lockManagerService;
}
@Override
Preconditions.checkNotNull(elanTag, "ElanTag cannot be null or empty!");
logger.info("onSubnetAddedToVpn: Subnet " + subnetId.getValue() + " being added to vpn");
+ long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
+ if (vpnId == VpnConstants.INVALID_ID) {
+ vpnInterfaceManager.waitForVpnInstance(vpnName, VpnConstants.PER_VPN_INSTANCE_MAX_WAIT_TIME_IN_MILLISECONDS, vpnInterfaceManager.getvpnInstanceToIdSynchronizerMap());
+ vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
+ if (vpnId == VpnConstants.INVALID_ID) {
+ logger.error("onSubnetAddedToVpn: VpnInstance to VPNId mapping not yet available for VpnName {} processing subnet {} with IP {} " +
+ ", bailing out now.", vpnName, subnetId, subnetIp);
+ return;
+ }
+ }
//TODO(vivek): Change this to use more granularized lock at subnetId level
- synchronized (this) {
+ try {
+ VpnUtil.lockSubnet(lockManager, subnetId.getValue());
try {
Subnetmap subMap = null;
// Please check if subnetId belongs to an External Network
InstanceIdentifier<Subnetmap> subMapid = InstanceIdentifier.builder(Subnetmaps.class).
child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
- Optional<Subnetmap> sm = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, subMapid);
+ Optional<Subnetmap> sm = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, subMapid);
if (!sm.isPresent()) {
logger.error("onSubnetAddedToVpn: Unable to retrieve subnetmap entry for subnet : " + subnetId);
return;
subMap = sm.get();
InstanceIdentifier<Networks> netsIdentifier = InstanceIdentifier.builder(ExternalNetworks.class).
child(Networks.class, new NetworksKey(subMap.getNetworkId())).build();
- Optional<Networks> optionalNets = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, netsIdentifier);
+ Optional<Networks> optionalNets = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, netsIdentifier);
if (optionalNets.isPresent()) {
logger.info("onSubnetAddedToVpn: subnet {} is an external subnet on external network {}, so ignoring this for SubnetRoute",
subnetId.getValue(), subMap.getNetworkId().getValue());
//Create and add SubnetOpDataEntry object for this subnet to the SubnetOpData container
InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
- Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker,
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker,
LogicalDatastoreType.OPERATIONAL,
subOpIdentifier);
if (optionalSubs.isPresent()) {
return;
}
logger.debug("onSubnetAddedToVpn: Creating new SubnetOpDataEntry node for subnet: " + subnetId.getValue());
- Map<BigInteger, SubnetToDpn> subDpnMap = new HashMap<>();
+ Map<BigInteger, SubnetToDpn> subDpnMap = new HashMap<BigInteger, SubnetToDpn>();
SubnetOpDataEntry subOpEntry = null;
BigInteger dpnId = null;
BigInteger nhDpnId = null;
SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder().setKey(new SubnetOpDataEntryKey(subnetId));
subOpBuilder.setSubnetId(subnetId);
subOpBuilder.setSubnetCidr(subnetIp);
- String rd = VpnUtil.getVpnRdFromVpnInstanceConfig(broker, vpnName);
+ String rd = VpnUtil.getVpnRdFromVpnInstanceConfig(dataBroker, vpnName);
if (rd == null) {
logger.error("onSubnetAddedToVpn: The VPN Instance name " + notification.getVpnName() + " does not have RD ");
return;
}
subOpBuilder.setVrfId(rd);
subOpBuilder.setVpnName(vpnName);
- subOpBuilder.setSubnetToDpn(new ArrayList<>());
+ subOpBuilder.setSubnetToDpn(new ArrayList<SubnetToDpn>());
subOpBuilder.setRouteAdvState(TaskState.Na);
subOpBuilder.setElanTag(elanTag);
List<Uuid> portList = subMap.getPortList();
if (portList != null) {
for (Uuid port: portList) {
- Interface intfState = InterfaceUtils.getInterfaceStateFromOperDS(broker,port.getValue());
+ Interface intfState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker,port.getValue());
if (intfState != null) {
- dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
- if (dpnId == null) {
+ try {
+ dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
+ } catch (Exception e) {
+ logger.error("onSubnetAddedToVpn: Unable to obtain dpnId for interface {},",
+ " subnetroute inclusion for this interface failed with exception {}",
+ port.getValue(), e);
+ continue;
+ }
+ if (dpnId.equals(BigInteger.ZERO)) {
logger.info("onSubnetAddedToVpn: Port " + port.getValue() + " is not assigned DPN yet, ignoring ");
continue;
}
}
}
if (subDpnMap.size() > 0) {
- subOpBuilder.setSubnetToDpn(new ArrayList<>(subDpnMap.values()));
+ subOpBuilder.setSubnetToDpn(new ArrayList<SubnetToDpn>(subDpnMap.values()));
}
}
if (nhDpnId != null) {
+ logger.info("Next-Hop dpn {} is available for rd {} subnetIp {} vpn {}", nhDpnId, rd, subnetIp, vpnName);
subOpBuilder.setNhDpnId(nhDpnId);
try {
/*
And also advertise the subnet route entry via BGP.
*/
int label = getLabel(rd, subnetIp);
- addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
- advertiseSubnetRouteToBgp(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
+ if (label == 0) {
+ logger.error("Unable to fetch label from Id Manager. Bailing out of handling addition of subnet {} to vpn {}", subnetIp, vpnName);
+ return;
+ }
+ addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
subOpBuilder.setRouteAdvState(TaskState.Done);
} catch (Exception ex) {
logger.error("onSubnetAddedToVpn: FIB rules and Advertising nhDpnId " + nhDpnId +
" information for subnet " + subnetId.getValue() + " to BGP failed {}", ex);
subOpBuilder.setRouteAdvState(TaskState.Pending);
}
- } else {
- try {
- /*
- Write the subnet route entry to the FIB.
- NOTE: Will not advertise to BGP as NextHopDPN is not available yet.
- */
- int label = getLabel(rd, subnetIp);
- addSubnetRouteToFib(rd, subnetIp, null, vpnName, elanTag, label);
- } catch (Exception ex) {
- logger.error("onSubnetAddedToVpn: FIB rules writing for subnet {} with exception {} " +
- subnetId.getValue(), ex);
- subOpBuilder.setRouteAdvState(TaskState.Pending);
- }
+ }else{
+ logger.info("Next-Hop dpn is unavailable for rd {} subnetIp {} vpn {}", rd, subnetIp, vpnName);
}
subOpEntry = subOpBuilder.build();
- MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
- logger.info("onSubnetAddedToVpn: Added subnetopdataentry to OP Datastore for subnet " + subnetId.getValue());
+ MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
+ logger.info("onSubnetAddedToVpn: Added subnetopdataentry to OP Datastore for subnet {}",
+ subnetId.getValue());
} catch (Exception ex) {
logger.error("Creation of SubnetOpDataEntry for subnet " +
subnetId.getValue() + " failed {}", ex);
} finally {
+ VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
}
+ } catch (Exception e) {
+ logger.error("Unable to handle subnet {} added to vpn {} {}", subnetIp, vpnName, e);
}
+
}
@Override
if (!notification.isExternalVpn()) {
return;
}
- logger.info("onSubnetDeletedFromVpn: Subnet " + subnetId.getValue() + " being removed to vpn");
+ logger.info("onSubnetDeletedFromVpn: Subnet " + subnetId.getValue() + " being removed from vpn");
//TODO(vivek): Change this to use more granularized lock at subnetId level
- synchronized (this) {
+ try {
+ VpnUtil.lockSubnet(lockManager, subnetId.getValue());
try {
InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
- child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
logger.trace(" Removing the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
- Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker,
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker,
LogicalDatastoreType.OPERATIONAL,
subOpIdentifier);
if (!optionalSubs.isPresent()) {
" not available in datastore");
return;
}
- SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
- List<SubnetToDpn> subDpnList = subOpBuilder.getSubnetToDpn();
- for (SubnetToDpn subDpn: subDpnList) {
- List<VpnInterfaces> vpnIntfList = subDpn.getVpnInterfaces();
- for (VpnInterfaces vpnIntf: vpnIntfList) {
- subOpDpnManager.removePortOpDataEntry(vpnIntf.getInterfaceName());
- }
- }
- //Removing Stale Ports in portOpData
+
+ /* If subnet is deleted (or if its removed from VPN), the ports that are DOWN on that subnet
+ * will continue to be stale in portOpData DS, as subDpnList used for portOpData removal will
+ * contain only ports that are UP. So here we explicitly cleanup the ports of the subnet by
+ * going through the list of ports on the subnet
+ */
InstanceIdentifier<Subnetmap> subMapid = InstanceIdentifier.builder(Subnetmaps.class).
child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
- Optional<Subnetmap> sm = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, subMapid);
+ Optional<Subnetmap> sm = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, subMapid);
if (!sm.isPresent()) {
logger.error("Stale ports removal: Unable to retrieve subnetmap entry for subnet : " + subnetId);
- }
- Subnetmap subMap = sm.get();
- List<Uuid> portList = subMap.getPortList();
- if(portList!=null){
- InstanceIdentifier<PortOpData> portOpIdentifier = InstanceIdentifier.builder(PortOpData.class).build();
- Optional<PortOpData> optionalPortOp = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
- if(!optionalPortOp.isPresent()){
- logger.error("Stale ports removal: Cannot delete port. Not available in data store");
- return;
- } else{
- PortOpData portOpData = optionalPortOp.get();
- List<PortOpDataEntry> portOpDataList = portOpData.getPortOpDataEntry();
- if(portOpDataList!=null){
- for(PortOpDataEntry portOpDataListEntry : portOpDataList){
- if(portList.contains(new Uuid(portOpDataListEntry.getPortId()))){
- logger.trace("Removing stale port: " + portOpDataListEntry + "for dissociated subnetId: " + subnetId);
- MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier.
- child(PortOpDataEntry.class, new PortOpDataEntryKey(portOpDataListEntry.getKey())));
- }
- }
+ } else {
+ Subnetmap subMap = sm.get();
+ List<Uuid> portList = subMap.getPortList();
+ if (portList != null) {
+ for (Uuid port : portList) {
+ InstanceIdentifier<PortOpDataEntry> portOpIdentifier = InstanceIdentifier.builder(PortOpData.class).
+ child(PortOpDataEntry.class, new PortOpDataEntryKey(port.getValue())).build();
+ logger.trace("Deleting portOpData entry for port " + port.getValue());
+ MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
}
}
}
+ SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
String rd = subOpBuilder.getVrfId();
String subnetIp = subOpBuilder.getSubnetCidr();
+ String vpnName = subOpBuilder.getVpnName();
BigInteger nhDpnId = subOpBuilder.getNhDpnId();
- MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier);
+ MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier);
logger.info("onSubnetDeletedFromVpn: Removed subnetopdataentry for subnet {} successfully from Datastore", subnetId.getValue());
try {
//Withdraw the routes for all the interfaces on this subnet
//Remove subnet route entry from FIB
- deleteSubnetRouteFromFib(rd, subnetIp);
- withdrawSubnetRoutefromBgp(rd, subnetIp);
+ deleteSubnetRouteFromFib(rd, subnetIp, vpnName);
} catch (Exception ex) {
logger.error("onSubnetAddedToVpn: Withdrawing routes from BGP for subnet " +
subnetId.getValue() + " failed {}" + ex);
logger.error("Removal of SubnetOpDataEntry for subnet " +
subnetId.getValue() + " failed {}" + ex);
} finally {
+ VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
}
+ } catch (Exception e) {
+ logger.error("Unable to handle subnet {} removed to vpn {} {}", notification.getSubnetIp(), notification.getVpnName(), e);
}
}
InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
- Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker,
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker,
LogicalDatastoreType.OPERATIONAL,
subOpIdentifier);
if (optionalSubs.isPresent()) {
} else {
if (notification.isExternalVpn()) {
SubnetAddedToVpnBuilder bldr = new SubnetAddedToVpnBuilder().setVpnName(vpnName).setElanTag(elanTag);
- bldr.setSubnetIp(subnetIp).setSubnetId(subnetId).setExternalVpn(true);
+ bldr.setSubnetIp(subnetIp).setSubnetId(subnetId).setExternalVpn(true);;
onSubnetAddedToVpn(bldr.build());
}
// TODO(vivek): Something got updated, but we donot know what ?
logger.info("onPortAddedToSubnet: Port " + portId.getValue() + " being added to subnet " + subnetId.getValue());
//TODO(vivek): Change this to use more granularized lock at subnetId level
- synchronized (this) {
+ try {
+ VpnUtil.lockSubnet(lockManager, subnetId.getValue());
try {
InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
- child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
- Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
subOpIdentifier);
if (!optionalSubs.isPresent()) {
logger.info("onPortAddedToSubnet: Port " + portId.getValue() + " is part of a subnet " + subnetId.getValue() +
" that is not in VPN, ignoring");
return;
}
- Interface intfState = InterfaceUtils.getInterfaceStateFromOperDS(broker,portId.getValue());
+ Interface intfState = InterfaceUtils.getInterfaceStateFromOperDS(dataBroker,portId.getValue());
if (intfState == null) {
// Interface State not yet available
subOpDpnManager.addPortOpDataEntry(portId.getValue(), subnetId, null);
return;
}
- BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
- if (dpnId == null) {
+ BigInteger dpnId = BigInteger.ZERO;
+ try {
+ dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
+ } catch (Exception e) {
+ logger.error("onSubnetAddedToVpn: Unable to obtain dpnId for interface {},",
+ " subnetroute inclusion for this interface failed with exception {}",
+ portId.getValue(), e);
+ return;
+ }
+ if (dpnId.equals(BigInteger.ZERO)) {
logger.info("onPortAddedToSubnet: Port " + portId.getValue() + " is not assigned DPN yet, ignoring ");
return;
}
// Write the Subnet Route Entry to FIB
// Advertise BGP Route here and set route_adv_state to DONE
int label = getLabel(rd, subnetIp);
- addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
- advertiseSubnetRouteToBgp(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
+ if (label == 0) {
+ logger.error("Unable to fetch label from Id Manager. Bailing out of handling addition of port {} to subnet {} in vpn {}", portId.getValue(), subnetIp, vpnName);
+ return;
+ }
+ addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
subOpBuilder.setRouteAdvState(TaskState.Done);
} catch (Exception ex) {
logger.error("onPortAddedToSubnet: Advertising NextHopDPN "+ nhDpnId +
}
}
SubnetOpDataEntry subOpEntry = subOpBuilder.build();
- MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
+ MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
logger.info("onPortAddedToSubnet: Updated subnetopdataentry to OP Datastore for port " + portId.getValue());
} catch (Exception ex) {
logger.error("Creation of SubnetOpDataEntry for subnet " +
subnetId.getValue() + " failed {}", ex);
} finally {
+ VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
}
+ } catch (Exception e) {
+ logger.error("Unable to handle port {} added to subnet {} {}", portId.getValue(), subnetId.getValue(), e);
}
}
logger.info("onPortRemovedFromSubnet: Port " + portId.getValue() + " being removed from subnet " + subnetId.getValue());
//TODO(vivek): Change this to use more granularized lock at subnetId level
- synchronized (this) {
+ try {
+ VpnUtil.lockSubnet(lockManager, subnetId.getValue());
try {
PortOpDataEntry portOpEntry = subOpDpnManager.removePortOpDataEntry(portId.getValue());
if (portOpEntry == null) {
boolean last = subOpDpnManager.removeInterfaceFromDpn(subnetId, dpnId, portId.getValue());
InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
- Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
subOpIdentifier);
if (!optionalSubs.isPresent()) {
logger.info("onPortRemovedFromSubnet: Port " + portId.getValue() + " is part of a subnet " + subnetId.getValue() +
subOpBuilder.setNhDpnId(null);
try {
// withdraw route from BGP
- deleteSubnetRouteFromFib(rd, subnetIp);
- withdrawSubnetRoutefromBgp(rd, subnetIp);
+ deleteSubnetRouteFromFib(rd, subnetIp, vpnName);
subOpBuilder.setRouteAdvState(TaskState.Na);
} catch (Exception ex) {
logger.error("onPortRemovedFromSubnet: Withdrawing NextHopDPN " + dpnId + " information for subnet " +
- subnetId.getValue() + " from BGP failed ", ex);
+ subnetId.getValue() + " from BGP failed ", ex);
subOpBuilder.setRouteAdvState(TaskState.Pending);
}
} else {
// Advertise the new NexthopIP to BGP for this subnet
//withdrawSubnetRoutefromBgp(rd, subnetIp);
int label = getLabel(rd, subnetIp);
- addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
- advertiseSubnetRouteToBgp(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
+ if (label == 0) {
+ logger.error("Unable to fetch label from Id Manager. Bailing out of handling removal of port {} from subnet {} in vpn {}", portId.getValue(), subnetIp, vpnName);
+ return;
+ }
+ addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
subOpBuilder.setRouteAdvState(TaskState.Done);
} catch (Exception ex) {
logger.error("onPortRemovedFromSubnet: Swapping Withdrawing NextHopDPN " + dpnId +
}
}
subOpEntry = subOpBuilder.build();
- MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
+ MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
logger.info("onPortRemovedFromSubnet: Updated subnetopdataentry to OP Datastore removing port " + portId.getValue());
} catch (Exception ex) {
logger.error("Creation of SubnetOpDataEntry for subnet " +
subnetId.getValue() + " failed {}" + ex);
} finally {
+ VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
}
+ } catch (Exception e) {
+ logger.error("Unable to handle port {} removed from subnet {} {}", portId.getValue(), subnetId.getValue(), e);
}
}
- 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");
- return;
- }
- BigInteger dpnId = portOpEntry.getDpnId();
- if (dpnId == null) {
- dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
- if (dpnId == null) {
- logger.error("onInterfaceUp: Unable to determine the DPNID for port " + intfName);
- return;
- }
+ SubnetToDpn subDpn = null;
+ PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(intfName);
+ if (portOpEntry == null) {
+ logger.info("onInterfaceUp: Port " + intfName + "is part of a subnet not in VPN, ignoring");
+ return;
+ }
+ if ((dpnId == null) || (dpnId == BigInteger.ZERO)) {
+ dpnId = portOpEntry.getDpnId();
+ if (dpnId == null) {
+ logger.error("onInterfaceUp: Unable to determine the DPNID for port " + intfName);
+ return;
}
- Uuid subnetId = portOpEntry.getSubnetId();
+ }
+ Uuid subnetId = portOpEntry.getSubnetId();
+ try {
+ VpnUtil.lockSubnet(lockManager, subnetId.getValue());
try {
InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
- child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
- Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
subOpIdentifier);
if (!optionalSubs.isPresent()) {
logger.error("onInterfaceUp: SubnetOpDataEntry for subnet " + subnetId.getValue() +
// Write the Subnet Route Entry to FIB
// Advertise BGP Route here and set route_adv_state to DONE
int label = getLabel(rd, subnetIp);
- addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
- advertiseSubnetRouteToBgp(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
+ if (label == 0) {
+ logger.error("Unable to fetch label from Id Manager. Bailing out of handling interface up event for port {} for subnet {} in vpn {}", intfName, subnetIp, vpnName);
+ return;
+ }
+ addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
subOpBuilder.setRouteAdvState(TaskState.Done);
} catch (Exception ex) {
logger.error("onInterfaceUp: Advertising NextHopDPN " + nhDpnId + " information for subnet " +
}
}
SubnetOpDataEntry subOpEntry = subOpBuilder.build();
- MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
+ MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
logger.info("onInterfaceUp: Updated subnetopdataentry to OP Datastore port up " + intfName);
} catch (Exception ex) {
logger.error("Creation of SubnetOpDataEntry for subnet " +
subnetId.getValue() + " failed {}" + ex);
} finally {
+ VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
}
+ } catch (Exception e) {
+ logger.error("Unable to handle interface up event for port {} in subnet {} {}", portOpEntry.getPortId(), subnetId.getValue(), e);
}
}
- 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);
- if (portOpEntry == null) {
- logger.info("onInterfaceDown: Port " + intfState.getName() + "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;
- }
- }
- Uuid subnetId = portOpEntry.getSubnetId();
+ PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(interfaceName);
+ if (portOpEntry == null) {
+ logger.info("onInterfaceDown: Port " + interfaceName + "is part of a subnet not in VPN, ignoring");
+ return;
+ }
+ if ((dpnId == null) ||(dpnId == BigInteger.ZERO)) {
+ logger.error("onInterfaceDown: Unable to determine the DPNID for port " + interfaceName);
+ return;
+ }
+ Uuid subnetId = portOpEntry.getSubnetId();
+ try {
+ VpnUtil.lockSubnet(lockManager, subnetId.getValue());
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,
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(dataBroker,
LogicalDatastoreType.OPERATIONAL,
subOpIdentifier);
if (!optionalSubs.isPresent()) {
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()) {
subOpBuilder.setNhDpnId(null);
try {
// Withdraw route from BGP for this subnet
- deleteSubnetRouteFromFib(rd, subnetIp);
- withdrawSubnetRoutefromBgp(rd, subnetIp);
+ deleteSubnetRouteFromFib(rd, subnetIp, vpnName);
subOpBuilder.setRouteAdvState(TaskState.Na);
} catch (Exception ex) {
logger.error("onInterfaceDown: Withdrawing NextHopDPN " + dpnId + " information for subnet " +
- subnetId.getValue() + " from BGP failed {}" + ex);
+ subnetId.getValue() + " from BGP failed {}" + ex);
subOpBuilder.setRouteAdvState(TaskState.Pending);
}
} else {
// Best effort Withdrawal of route from BGP for this subnet
//withdrawSubnetRoutefromBgp(rd, subnetIp);
int label = getLabel(rd, subnetIp);
- addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
- advertiseSubnetRouteToBgp(rd, subnetIp, nhDpnId, vpnName, elanTag, label);
+ if (label == 0) {
+ logger.error("Unable to fetch label from Id Manager. Bailing out of handling interface down event for port {} in subnet {} for vpn {}", interfaceName, subnetIp, vpnName);
+ return;
+ }
+ addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag, label, subnetId);
subOpBuilder.setRouteAdvState(TaskState.Done);
} catch (Exception ex) {
logger.error("onInterfaceDown: Swapping Withdrawing NextHopDPN " + dpnId + " information for subnet " +
}
}
subOpEntry = subOpBuilder.build();
- MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
- logger.info("onInterfaceDown: Updated subnetopdataentry to OP Datastore port down " + intfName);
+ MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
+ 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);
} finally {
+ VpnUtil.unlockSubnet(lockManager, subnetId.getValue());
}
+ } catch (Exception e) {
+ logger.error("Unable to handle interface down event for port {} in subnet {} {}", portOpEntry.getPortId(), subnetId.getValue(), e);
}
}
+ @Override
+ public void onRouterAssociatedToVpn(RouterAssociatedToVpn notification) {
+ }
+
+ @Override
+ public void onRouterDisassociatedFromVpn(RouterDisassociatedFromVpn notification) {
+ }
+
private void addSubnetRouteToFib(String rd, String subnetIp, BigInteger nhDpnId, String vpnName,
- Long elanTag, int label) {
+ Long elanTag, int label, Uuid subnetId) throws Exception {
Preconditions.checkNotNull(rd, "RouteDistinguisher cannot be null or empty!");
Preconditions.checkNotNull(subnetIp, "SubnetRouteIp cannot be null or empty!");
Preconditions.checkNotNull(vpnName, "vpnName cannot be null or empty!");
Preconditions.checkNotNull(elanTag, "elanTag cannot be null or empty!");
String nexthopIp = null;
- if (nhDpnId != null) {
- nexthopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, nhDpnId);
+ try {
+ nexthopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, nhDpnId);
+ } catch (Exception e) {
+ logger.warn("Unable to find nexthopip for subnetroute subnetip {}", subnetIp);
+ return;
+ }
+ if (nexthopIp != null) {
+ VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, VpnUtil.getPrefixToInterfaceIdentifier(VpnUtil.getVpnId(dataBroker, vpnName), subnetIp), VpnUtil.getPrefixToInterface(nhDpnId, subnetId.getValue(), subnetIp));
+ vpnInterfaceManager.addSubnetRouteFibEntryToDS(rd, vpnName, subnetIp, nexthopIp, label, elanTag, nhDpnId, null);
+ try {
+ // BGPManager (inside ODL) requires a withdraw followed by advertise
+ // due to bugs with ClusterDataChangeListener used by BGPManager.
+ //bgpManager.withdrawPrefix(rd, subnetIp);
+ bgpManager.advertisePrefix(rd, subnetIp, Arrays.asList(nexthopIp), label);
+ } catch (Exception e) {
+ logger.error("Fail: Subnet route not advertised for rd {} subnetIp {}", rd, subnetIp, e);
+ throw e;
+ }
+ } else {
+ logger.warn("The nexthopip is empty for subnetroute subnetip {}, ignoring fib route addition", subnetIp);
}
- vpnInterfaceManager.addSubnetRouteFibEntryToDS(rd, subnetIp, nexthopIp, label, elanTag);
}
private int getLabel(String rd, String subnetIp) {
int label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
- VpnUtil.getNextHopLabelKey(rd, subnetIp));
+ VpnUtil.getNextHopLabelKey(rd, subnetIp));
logger.trace("Allocated subnetroute label {} for rd {} prefix {}", label, rd, subnetIp);
return label;
}
- private void deleteSubnetRouteFromFib(String rd, String subnetIp) {
- Preconditions.checkNotNull(rd, "RouteDistinguisher cannot be null or empty!");
- Preconditions.checkNotNull(subnetIp, "SubnetRouteIp cannot be null or empty!");
- vpnInterfaceManager.removeFibEntryFromDS(rd, subnetIp);
- }
-
- private void advertiseSubnetRouteToBgp(String rd, String subnetIp, BigInteger nhDpnId, String vpnName,
- Long elanTag, int label) throws Exception {
+ private void deleteSubnetRouteFromFib(String rd, String subnetIp, String vpnName) throws Exception {
Preconditions.checkNotNull(rd, "RouteDistinguisher cannot be null or empty!");
Preconditions.checkNotNull(subnetIp, "SubnetRouteIp cannot be null or empty!");
- Preconditions.checkNotNull(elanTag, "elanTag cannot be null or empty!");
- Preconditions.checkNotNull(nhDpnId, "nhDpnId cannot be null or empty!");
- Preconditions.checkNotNull(vpnName, "vpnName cannot be null or empty!");
- String nexthopIp = null;
- nexthopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, nhDpnId);
- if (nexthopIp == null) {
- logger.error("createSubnetRouteInVpn: Unable to obtain endpointIp address for DPNId " + nhDpnId);
- throw new Exception("Unable to obtain endpointIp address for DPNId " + nhDpnId);
- }
+ vpnInterfaceManager.deleteSubnetRouteFibEntryFromDS(rd, subnetIp, vpnName);
try {
- // BGPManager (inside ODL) requires a withdraw followed by advertise
- // due to bugs with ClusterDataChangeListener used by BGPManager.
bgpManager.withdrawPrefix(rd, subnetIp);
- bgpManager.advertisePrefix(rd, subnetIp, nexthopIp, label);
} catch (Exception e) {
- logger.error("Subnet route not advertised for rd " + rd + " failed ", e);
+ logger.error("Fail: Subnet route not withdrawn for rd {} subnetIp {}", rd, subnetIp, e);
throw e;
}
}
-
- private void withdrawSubnetRoutefromBgp(String rd, String subnetIp) throws Exception {
- Preconditions.checkNotNull(rd, "RouteDistinguisher cannot be null or empty!");
- Preconditions.checkNotNull(subnetIp, "SubnetIp cannot be null or empty!");
- try {
- bgpManager.withdrawPrefix(rd, subnetIp);
- } catch (Exception e) {
- logger.error("Subnet route not advertised for rd " + rd + " failed ", e);
- throw e;
- }
- }
-
- @Override
- public void onRouterAssociatedToVpn(RouterAssociatedToVpn notification) {
- }
-
- @Override
- public void onRouterDisassociatedFromVpn(RouterDisassociatedFromVpn notification) {
-
- }
}