use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstance in project netvirt by opendaylight.
the class VPNServiceChainHandler method programVpnToScfPipeline.
/**
* Programs the necessary flows in LFIB and LPortDispatcher table so that
* the packets coming from a given VPN are delivered to a given
* ServiceChain Pipeline.
*
* @param vpnName Name of the VPN. Typically the UUID
* @param tableId Table to which the LPortDispatcher table sends the packet
* to (Uplink or Downlink Subsc table)
* @param scfTag Scf tag to the SCF to which the Vpn is linked to.
* @param lportTag VpnPseudo Port lportTag
* @param addOrRemove States if the VPN2SCF Pipeline must be installed or
* removed
*/
public void programVpnToScfPipeline(String vpnName, short tableId, long scfTag, int lportTag, int addOrRemove) {
// This entries must be created in the DPN where the CGNAT is installed. Since it is not possible
// to know where CGNAT is located, this entries are installed in all the VPN footprint.
// LFIB:
// - Match: cgnatLabel Instr: lportTag=vpnPseudoPortTag + SI=SCF + GOTO 17
// LportDisp:
// - Match: vpnPseudoPortTag + SI==SCF Instr: scfTag + GOTO 70
LOG.info("programVpnToScfPipeline ({}) : Parameters VpnName:{} tableId:{} scftag:{} lportTag:{}", addOrRemove == NwConstants.ADD_FLOW ? "Creation" : "Removal", vpnName, tableId, scfTag, lportTag);
String rd = VpnServiceChainUtils.getVpnRd(dataBroker, vpnName);
LOG.debug("Router distinguisher (rd):{}", rd);
if (rd == null || rd.isEmpty()) {
LOG.warn("programVpnToScfPipeline: Could not find Router-distinguisher for VPN {}. No further actions", vpnName);
return;
}
VpnInstanceOpDataEntry vpnInstance = getVpnInstance(rd);
if (vpnInstance == null) {
LOG.warn("Could not find a suitable VpnInstance for Route-Distinguisher={}", rd);
return;
}
// Find out the set of DPNs for the given VPN ID
Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
List<VrfEntry> vrfEntries = VpnServiceChainUtils.getAllVrfEntries(dataBroker, rd);
if (vrfEntries != null) {
if (addOrRemove == NwConstants.ADD_FLOW) {
AddVpnPseudoPortDataJob updateVpnToPseudoPortTask = new AddVpnPseudoPortDataJob(dataBroker, rd, lportTag, tableId, (int) scfTag);
jobCoordinator.enqueueJob(updateVpnToPseudoPortTask.getDsJobCoordinatorKey(), updateVpnToPseudoPortTask);
} else {
RemoveVpnPseudoPortDataJob removeVpnPseudoPortDataTask = new RemoveVpnPseudoPortDataJob(dataBroker, rd);
jobCoordinator.enqueueJob(removeVpnPseudoPortDataTask.getDsJobCoordinatorKey(), removeVpnPseudoPortDataTask);
}
for (VpnToDpnList dpnInVpn : vpnToDpnList) {
BigInteger dpnId = dpnInVpn.getDpnId();
programVpnToScfPipelineOnDpn(dpnId, vrfEntries, tableId, (int) scfTag, lportTag, addOrRemove);
if (dpnInVpn.getVpnInterfaces() != null) {
long vpnId = vpnInstance.getVpnId();
Flow flow = VpnServiceChainUtils.buildLPortDispFromScfToL3VpnFlow(vpnId, dpnId, lportTag, NwConstants.ADD_FLOW);
if (addOrRemove == NwConstants.ADD_FLOW) {
mdsalManager.installFlow(dpnId, flow);
} else {
mdsalManager.removeFlow(dpnId, flow);
}
dpnInVpn.getVpnInterfaces().forEach(vpnIf -> {
if (addOrRemove == NwConstants.ADD_FLOW) {
bindScfOnVpnInterface(vpnIf.getInterfaceName(), (int) scfTag);
} else {
unbindScfOnVpnInterface(vpnIf.getInterfaceName());
}
});
}
}
}
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstance in project netvirt by opendaylight.
the class CloudScVpnInterfaceListener method add.
@Override
protected void add(InstanceIdentifier<VpnInterface> key, VpnInterface vpnIfaceAdded) {
for (VpnInstanceNames vpnInstance : vpnIfaceAdded.getVpnInstanceNames()) {
String vpnName = vpnInstance.getVpnName();
if (!vpnInstance.getAssociatedSubnetType().equals(AssociatedSubnetType.V4AndV6Subnets) && !vpnInstance.getAssociatedSubnetType().equals(AssociatedSubnetType.V4Subnet)) {
continue;
}
try {
Optional<VpnToPseudoPortData> optScfInfoForVpn = vpnScHandler.getScfInfoForVpn(vpnName);
if (!optScfInfoForVpn.isPresent()) {
LOG.trace("Vpn {} is not related to ServiceChaining. No further action", vpnName);
return;
}
vpnScHandler.bindScfOnVpnInterface(vpnIfaceAdded.key().getName(), optScfInfoForVpn.get().getScfTag());
} catch (InterruptedException | ExecutionException e) {
LOG.error("Error reading the ServiceChaining information for VPN {}", vpnName, e);
}
}
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstance in project netvirt by opendaylight.
the class ExternalRoutersListener method addOrDelDefFibRouteToSNAT.
private void addOrDelDefFibRouteToSNAT(String routerName, Uint32 routerId, Uint32 bgpVpnId, Uuid bgpVpnUuid, boolean create, TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
// Check if BGP VPN exists. If exists then invoke the new method.
if (bgpVpnId != NatConstants.INVALID_ID) {
if (bgpVpnUuid != null) {
String bgpVpnName = bgpVpnUuid.getValue();
LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
RouterIds rtrs = new RouterIdsBuilder().withKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
confTx.mergeParentStructurePut(getRoutersIdentifier(bgpVpnId), rtrs);
}
if (create) {
addDefaultFibRouteForSnatWithBgpVpn(routerName, routerId, bgpVpnId, confTx);
} else {
removeDefaultFibRouteForSnatWithBgpVpn(routerName, routerId, bgpVpnId, confTx);
}
return;
}
// Router ID is used as the internal VPN's name, hence the vrf-id in VpnInstance Op DataStore
addOrDelDefaultFibRouteForSNAT(routerName, routerId, create, confTx);
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstance in project netvirt by opendaylight.
the class EvpnDnatFlowProgrammer method onAddFloatingIp.
public void onAddFloatingIp(final Uint64 dpnId, final String routerName, final Uint32 routerId, final String vpnName, final String internalIp, final String externalIp, final Uuid networkId, final String interfaceName, final String floatingIpInterface, final String floatingIpPortMacAddress, final String rd, final String nextHopIp, final TypedReadWriteTransaction<Configuration> confTx) {
/*
* 1) Install the flow INTERNAL_TUNNEL_TABLE (table=36)-> PDNAT_TABLE (table=25) (SNAT VM on DPN1 is
* responding back to FIP VM on DPN2) {SNAT to DNAT traffic on different Hypervisor}
*
* 2) Install the flow L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25) (FIP VM1 to FIP VM2
* Traffic on Same Hypervisor) {DNAT to DNAT on Same Hypervisor}
*
* 3) Install the flow L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
* (DC-GW is responding back to FIP VM) {DNAT Reverse traffic})
*
*/
Uint32 vpnId = NatUtil.getVpnId(dataBroker, vpnName);
if (vpnId == NatConstants.INVALID_ID) {
LOG.error("onAddFloatingIp : Invalid Vpn Id is found for Vpn Name {}", vpnName);
return;
}
Uint32 l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
LOG.debug("onAddFloatingIp : L3VNI value is not configured in Internet VPN {} and RD {} " + "Carve-out L3VNI value from OpenDaylight VXLAN VNI Pool and continue with installing " + "DNAT flows for FloatingIp {}", vpnName, rd, externalIp);
l3Vni = natOverVxlanUtil.getInternetVpnVni(vpnName, routerId);
}
FloatingIPListener.updateOperationalDS(dataBroker, routerName, interfaceName, NatConstants.DEFAULT_LABEL_VALUE, internalIp, externalIp);
String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
// Inform to FIB and BGP
NatEvpnUtil.addRoutesForVxLanProvType(dataBroker, bgpManager, fibManager, vpnName, rd, fibExternalIp, nextHopIp, l3Vni, floatingIpInterface, floatingIpPortMacAddress, confTx, RouteOrigin.STATIC, dpnId, networkId);
/* Install the flow table L3_FIB_TABLE (table=21)-> PDNAT_TABLE (table=25)
* (SNAT to DNAT reverse traffic: If the DPN has both SNAT and DNAT configured )
*/
List<ActionInfo> actionInfoFib = new ArrayList<>();
actionInfoFib.add(new ActionSetFieldEthernetDestination(new MacAddress(floatingIpPortMacAddress)));
List<Instruction> instructionsFib = new ArrayList<>();
instructionsFib.add(new InstructionApplyActions(actionInfoFib).buildInstruction(0));
instructionsFib.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(1));
CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(fibExternalIp).setServiceId(l3Vni).setIpAddressSource(CreateFibEntryInput.IpAddressSource.FloatingIP).setInstruction(instructionsFib).build();
ListenableFuture<RpcResult<CreateFibEntryOutput>> futureVxlan = fibService.createFibEntry(input);
LOG.debug("onAddFloatingIp : Add Floating Ip {} , found associated to fixed port {}", externalIp, interfaceName);
if (floatingIpPortMacAddress != null) {
LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
vpnManager.addSubnetMacIntoVpnInstance(vpnName, null, floatingIpPortMacAddress, dpnId, tx);
vpnManager.addArpResponderFlowsToExternalNetworkIps(routerName, Collections.singleton(externalIp), floatingIpPortMacAddress, dpnId, networkId);
}), LOG, "Error processing floating IP port with MAC address {}", floatingIpPortMacAddress);
}
final Uint32 finalL3Vni = l3Vni;
Futures.addCallback(futureVxlan, new FutureCallback<RpcResult<CreateFibEntryOutput>>() {
@Override
public void onFailure(@NonNull Throwable error) {
LOG.error("onAddFloatingIp : Error {} in custom fib routes install process for Floating " + "IP Prefix {} on DPN {}", error, externalIp, dpnId);
}
@Override
public void onSuccess(@NonNull RpcResult<CreateFibEntryOutput> result) {
if (result.isSuccessful()) {
LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, innerConfTx -> {
LOG.info("onAddFloatingIp : Successfully installed custom FIB routes for Floating " + "IP Prefix {} on DPN {}", externalIp, dpnId);
List<Instruction> instructions = new ArrayList<>();
List<ActionInfo> actionsInfos = new ArrayList<>();
List<Instruction> customInstructions = new ArrayList<>();
customInstructions.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(0));
actionsInfos.add(new ActionNxResubmit(NwConstants.PDNAT_TABLE));
instructions.add(new InstructionApplyActions(actionsInfos).buildInstruction(0));
/* If more than one floatingIp is available in vpn-to-dpn-list for given dpn id, do not
call for
* installing INTERNAL_TUNNEL_TABLE (table=36) -> PDNAT_TABLE (table=25) flow entry with
* same tunnel_id
* again and again.
*/
if (!NatUtil.isFloatingIpPresentForDpn(dataBroker, dpnId, rd, vpnName, externalIp, true)) {
makeTunnelTableEntry(dpnId, finalL3Vni, instructions, innerConfTx);
}
/* Install the flow L3_GW_MAC_TABLE (table=19)-> PDNAT_TABLE (table=25)
* (DNAT reverse traffic: If the traffic is Initiated from DC-GW to FIP VM (DNAT forward
* traffic))
*/
NatEvpnUtil.makeL3GwMacTableEntry(dpnId, vpnId, floatingIpPortMacAddress, customInstructions, mdsalManager, innerConfTx);
}), LOG, "Error installing DNAT flows");
} else {
LOG.error("onAddFloatingIp : Error {} in rpc call to create custom Fib entries for Floating " + "IP Prefix {} on DPN {}", result.getErrors(), externalIp, dpnId);
}
}
}, MoreExecutors.directExecutor());
// Read the FIP vpn-interface details from Configuration l3vpn:vpn-interfaces model and write into Operational DS
InstanceIdentifier<VpnInterface> vpnIfIdentifier = NatUtil.getVpnInterfaceIdentifier(floatingIpInterface);
Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
if (optionalVpnInterface.isPresent()) {
LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, tx -> {
for (VpnInstanceNames vpnInstance : optionalVpnInterface.get().nonnullVpnInstanceNames().values()) {
if (!vpnName.equals(vpnInstance.getVpnName())) {
continue;
}
VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
VpnInterfaceOpDataEntryBuilder vpnIfOpDataEntryBuilder = new VpnInterfaceOpDataEntryBuilder();
vpnIfOpDataEntryBuilder.withKey(new VpnInterfaceOpDataEntryKey(interfaceName, vpnName));
Map<AdjacencyKey, Adjacency> keyAdjacencyMap = adjs != null && adjs.getAdjacency() != null ? adjs.nonnullAdjacency() : new HashMap<>();
List<Adjacency> adjacencyListToImport = new ArrayList<>();
for (Adjacency adj : keyAdjacencyMap.values()) {
Subnetmap sn = VpnHelper.getSubnetmapFromItsUuid(dataBroker, adj.getSubnetId());
if (!VpnHelper.isSubnetPartOfVpn(sn, vpnName)) {
continue;
}
adjacencyListToImport.add(adj);
}
AdjacenciesOp adjacenciesOp = new AdjacenciesOpBuilder().setAdjacency(adjacencyListToImport).build();
vpnIfOpDataEntryBuilder.addAugmentation(adjacenciesOp);
LOG.debug("onAddFloatingIp : Add vpnInterface {} to Operational l3vpn:vpn-interfaces-op-data ", floatingIpInterface);
InstanceIdentifier<VpnInterfaceOpDataEntry> vpnIfIdentifierOpDataEntry = NatUtil.getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnName);
tx.mergeParentStructurePut(vpnIfIdentifierOpDataEntry, vpnIfOpDataEntryBuilder.build());
break;
}
}), LOG, "onAddFloatingIp : Could not write Interface {}, vpnName {}", interfaceName, vpnName);
} else {
LOG.debug("onAddFloatingIp : No vpnInterface {} found in Configuration l3vpn:vpn-interfaces ", floatingIpInterface);
}
}
use of org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstance in project netvirt by opendaylight.
the class FloatingIPListener method removeNATFlowEntries.
void removeNATFlowEntries(Uint64 dpnId, String interfaceName, String vpnName, String routerName, InternalToExternalPortMap mapping, TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
String internalIp = mapping.getInternalIp();
String externalIp = mapping.getExternalIp();
Uint32 routerId = NatUtil.getVpnId(dataBroker, routerName);
if (routerId == NatConstants.INVALID_ID) {
LOG.error("removeNATFlowEntries : Could not retrieve router id for {} to remove NAT Flow entries", routerName);
return;
}
VpnInstance vpnInstance = NatUtil.getVpnIdToVpnInstance(dataBroker, vpnName);
if (vpnInstance == null || vpnInstance.getVpnId() == null) {
LOG.warn("removeNATFlowEntries: VPN Id not found for {} to remove NAT flow entries {}", vpnName, internalIp);
return;
}
Uint32 vpnId = vpnInstance.getVpnId();
String vrfId = vpnInstance.getVrfId();
// Delete the DNAT and SNAT table entries
removeDNATTblEntry(dpnId, internalIp, externalIp, routerId, confTx);
removeSNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId, confTx);
// Remove the DNAT default FIB flow L3_FIB_TABLE (21) -> PSNAT_TABLE (26) if SNAT is disabled
boolean isSnatEnabled = NatUtil.isSnatEnabledForRouterId(dataBroker, routerName);
if (!isSnatEnabled) {
addOrDelDefaultFibRouteForDnat(dpnId, routerName, routerId, confTx, false);
}
Uuid externalNetworkId = NatUtil.getNetworkIdFromRouterName(dataBroker, routerName);
ProviderTypes provType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerName, externalNetworkId);
if (provType == null) {
LOG.error("removeNATFlowEntries : External Network Provider Type Missing");
return;
}
if (provType == ProviderTypes.VXLAN) {
floatingIPHandler.cleanupFibEntries(dpnId, vpnName, externalIp, NatConstants.DEFAULT_L3VNI_VALUE, vrfId, confTx, provType);
removeOperationalDS(routerName, interfaceName, internalIp);
return;
}
Uint32 label = getOperationalIpMapping(routerName, interfaceName, internalIp);
if (label != null && label.longValue() < 0) {
LOG.error("removeNATFlowEntries : Could not retrieve label for prefix {} in router {}", internalIp, routerId);
return;
}
if (provType == ProviderTypes.VXLAN) {
floatingIPHandler.cleanupFibEntries(dpnId, vpnName, externalIp, NatConstants.DEFAULT_L3VNI_VALUE, vrfId, confTx, provType);
removeOperationalDS(routerName, interfaceName, internalIp);
return;
}
floatingIPHandler.cleanupFibEntries(dpnId, vpnName, externalIp, label, vrfId, confTx, provType);
removeOperationalDS(routerName, interfaceName, internalIp);
}
Aggregations