use of org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Tunnel in project netvirt by opendaylight.
the class NatUtil method isFloatingIpPresentForDpn.
public static boolean isFloatingIpPresentForDpn(DataBroker dataBroker, Uint64 dpnId, String rd, String vpnName, String externalIp, Boolean isMoreThanOneFipCheckOnDpn) {
InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
Optional<VpnToDpnList> dpnInVpn;
try {
dpnInVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
} catch (ExecutionException | InterruptedException e) {
LOG.error("isFloatingIpPresentForDpn: Exception while reading VpnToDpnList DS for the rd {} dpnId {}", rd, dpnId, e);
return false;
}
if (dpnInVpn.isPresent()) {
LOG.debug("isFloatingIpPresentForDpn : vpn-to-dpn-list is not empty for vpnName {}, dpn id {}, " + "rd {} and floatingIp {}", vpnName, dpnId, rd, externalIp);
try {
Map<IpAddressesKey, IpAddresses> keyIpAddressesMap = dpnInVpn.get().getIpAddresses();
if (keyIpAddressesMap != null && !keyIpAddressesMap.isEmpty()) {
int floatingIpPresentCount = 0;
for (IpAddresses ipAddress : keyIpAddressesMap.values()) {
if (!Objects.equals(ipAddress.getIpAddress(), externalIp) && IpAddresses.IpAddressSource.FloatingIP.equals(ipAddress.getIpAddressSource())) {
floatingIpPresentCount++;
// Add tunnel table check
if (isMoreThanOneFipCheckOnDpn && floatingIpPresentCount > 1) {
return true;
}
// Remove tunnel table check
if (!isMoreThanOneFipCheckOnDpn) {
return true;
}
}
}
} else {
LOG.debug("isFloatingIpPresentForDpn : vpn-to-dpn-list does not contain any floating IP for DPN {}", dpnId);
return false;
}
} catch (NullPointerException e) {
LOG.error("isFloatingIpPresentForDpn: Exception occurred on getting external IP address from " + "vpn-to-dpn-list on Dpn {}", dpnId, e);
return false;
}
}
return false;
}
use of org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Tunnel in project netvirt by opendaylight.
the class VpnFloatingIpHandler method onAddFloatingIp.
@Override
public void onAddFloatingIp(final Uint64 dpnId, final String routerUuid, final Uint32 routerId, final Uuid networkId, final String interfaceName, final InternalToExternalPortMap mapping, final String rd, TypedReadWriteTransaction<Configuration> confTx) {
String externalIp = mapping.getExternalIp();
String internalIp = mapping.getInternalIp();
Uuid floatingIpId = mapping.getExternalId();
Uuid subnetId = NatUtil.getFloatingIpPortSubnetIdFromFloatingIpId(dataBroker, floatingIpId);
String floatingIpPortMacAddress = NatUtil.getFloatingIpPortMacFromFloatingIpId(dataBroker, floatingIpId);
if (floatingIpPortMacAddress == null) {
LOG.error("onAddFloatingIp: Unable to retrieve floatingIp port MAC address from floatingIpId {} for " + "router {} to handle floatingIp {}", floatingIpId, routerUuid, externalIp);
return;
}
Optional<Subnets> externalSubnet = NatUtil.getOptionalExternalSubnets(dataBroker, subnetId);
final String vpnName = externalSubnet.isPresent() ? subnetId.getValue() : NatUtil.getAssociatedVPN(dataBroker, networkId);
final String subnetVpnName = externalSubnet.isPresent() ? subnetId.getValue() : null;
if (vpnName == null) {
LOG.error("onAddFloatingIp: No VPN is associated with ext nw {} to handle add floating ip {} configuration " + "for router {}", networkId, externalIp, routerId);
return;
}
if (rd == null) {
LOG.error("onAddFloatingIp: Unable to retrieve external (internet) VPN RD from external VPN {} for " + "router {} to handle floatingIp {}", vpnName, routerId, externalIp);
return;
}
ProviderTypes provType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker, routerUuid, networkId);
if (provType == null) {
return;
}
/*
* For external network of type GRE, it is required to use "Internet VPN VNI" for intra-DC
* communication, but we still require "MPLS labels" to reach SNAT/DNAT VMs from external
* entities via MPLSOverGRE.
*
* MPLSOverGRE based external networks, the ``opendaylight-vni-ranges`` pool will be
* used to carve out a unique VNI per Internet VPN (GRE-provider-type) to be used in the
* datapath for traffic forwarding for ``SNAT-to-DNAT`` and ``DNAT-to-DNAT`` cases within the
* DataCenter.
*/
String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
LOG.debug("onAddFloatingIp: Nexthop ip for prefix {} is {}", externalIp, nextHopIp);
if (provType == ProviderTypes.VXLAN) {
Uuid floatingIpInterface = NatEvpnUtil.getFloatingIpInterfaceIdFromFloatingIpId(dataBroker, floatingIpId);
evpnDnatFlowProgrammer.onAddFloatingIp(dpnId, routerUuid, routerId, vpnName, internalIp, externalIp, networkId, interfaceName, floatingIpInterface.getValue(), floatingIpPortMacAddress, rd, nextHopIp, confTx);
return;
}
/*
* MPLS label will be used to advertise prefixes and in "L3_LFIB_TABLE" (table 20) taking the packet
* to "INBOUND_NAPT_TABLE" (table 44) and "PDNAT_TABLE" (table 25).
*/
GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
ListenableFuture<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
ListenableFuture<RpcResult<CreateFibEntryOutput>> future = Futures.transformAsync(labelFuture, result -> {
if (result.isSuccessful()) {
GenerateVpnLabelOutput output = result.getResult();
Uint32 label = output.getLabel();
LOG.debug("onAddFloatingIp : Generated label {} for prefix {}", label, externalIp);
FloatingIPListener.updateOperationalDS(dataBroker, routerUuid, interfaceName, label, internalIp, externalIp);
/*
* For external network of type VXLAN all packets going from VMs within the DC, towards the
* external gateway device via the External VXLAN Tunnel,we are setting the VXLAN Tunnel ID to
* the L3VNI value of VPNInstance to which the VM belongs to.
*/
Uint32 l3vni = Uint32.ZERO;
if (NatUtil.isOpenStackVniSemanticsEnforcedForGreAndVxlan(elanService, provType)) {
l3vni = natOverVxlanUtil.getInternetVpnVni(vpnName, l3vni);
}
String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
// Inform BGP
NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd, fibExternalIp, nextHopIp, networkId.getValue(), floatingIpPortMacAddress, label, l3vni, RouteOrigin.STATIC, dpnId);
List<Instruction> instructions = new ArrayList<>();
List<ActionInfo> actionsInfos = new ArrayList<>();
actionsInfos.add(new ActionNxResubmit(NwConstants.PDNAT_TABLE));
instructions.add(new InstructionApplyActions(actionsInfos).buildInstruction(0));
List<ActionInfo> actionInfoFib = new ArrayList<>();
List<Instruction> customInstructions = new ArrayList<>();
actionInfoFib.add(new ActionSetFieldEthernetDestination(new MacAddress(floatingIpPortMacAddress)));
customInstructions.add(new InstructionApplyActions(actionInfoFib).buildInstruction(0));
customInstructions.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(1));
LoggingFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, innerConfTx -> {
makeTunnelTableEntry(vpnName, dpnId, label, instructions, innerConfTx, provType);
makeLFibTableEntry(dpnId, label, floatingIpPortMacAddress, NwConstants.PDNAT_TABLE, innerConfTx);
}), LOG, "Error adding tunnel or FIB table entries");
CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setInstruction(customInstructions).setIpAddress(fibExternalIp).setServiceId(label).setIpAddressSource(CreateFibEntryInput.IpAddressSource.FloatingIP).setInstruction(customInstructions).build();
// Future<RpcResult<java.lang.Void>> createFibEntry(CreateFibEntryInput input);
ListenableFuture<RpcResult<CreateFibEntryOutput>> future1 = fibService.createFibEntry(input);
LOG.debug("onAddFloatingIp : Add Floating Ip {} , found associated to fixed port {}", externalIp, interfaceName);
String networkVpnName = NatUtil.getAssociatedVPN(dataBroker, networkId);
txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
vpnManager.addSubnetMacIntoVpnInstance(networkVpnName, subnetVpnName, floatingIpPortMacAddress, dpnId, tx);
vpnManager.addArpResponderFlowsToExternalNetworkIps(routerUuid, Collections.singleton(externalIp), floatingIpPortMacAddress, dpnId, networkId);
});
return future1;
} else {
String errMsg = String.format("onAddFloatingIp : Could not retrieve the label for prefix %s " + "in VPN %s, %s", externalIp, vpnName, result.getErrors());
LOG.error(errMsg);
return Futures.immediateFailedFuture(new RuntimeException(errMsg));
}
}, MoreExecutors.directExecutor());
Futures.addCallback(future, new FutureCallback<RpcResult<CreateFibEntryOutput>>() {
@Override
public void onFailure(@NonNull Throwable error) {
LOG.error("onAddFloatingIp : Error in generate label or fib install process", error);
}
@Override
public void onSuccess(@NonNull RpcResult<CreateFibEntryOutput> result) {
if (result.isSuccessful()) {
LOG.info("onAddFloatingIp : Successfully installed custom FIB routes for prefix {}", externalIp);
} else {
LOG.error("onAddFloatingIp : Error in rpc call to create custom Fib entries for prefix {} " + "in DPN {}, {}", externalIp, dpnId, result.getErrors());
}
}
}, MoreExecutors.directExecutor());
// Handle GARP transmission
final IpAddress extrenalAddress = IpAddressBuilder.getDefaultInstance(externalIp);
sendGarpOnInterface(dpnId, networkId, extrenalAddress, floatingIpPortMacAddress);
}
use of org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Tunnel in project netvirt by opendaylight.
the class NatTunnelInterfaceStateListener method hndlTepEvntsForDpn.
private void hndlTepEvntsForDpn(StateTunnelList stateTunnelList, TunnelAction tunnelAction) {
LOG.trace("hndlTepEvntsForDpn : stateTunnelList {}", stateTunnelList);
final Uint64 srcDpnId = stateTunnelList.getSrcInfo() != null ? Uint64.valueOf(stateTunnelList.getSrcInfo().getTepDeviceId()) : Uint64.ZERO;
final String srcTepIp = stateTunnelList.getSrcInfo() != null ? stateTunnelList.getSrcInfo().getTepIp().stringValue() : null;
final String destTepIp = stateTunnelList.getDstInfo() != null ? stateTunnelList.getDstInfo().getTepIp().stringValue() : null;
LOG.trace("hndlTepEvntsForDpn : Handle tunnel event for srcDpn {} SrcTepIp {} DestTepIp {} ", srcDpnId, srcTepIp, destTepIp);
if (srcDpnId == Uint64.ZERO || srcTepIp == null || destTepIp == null) {
LOG.error("hndlTepEvntsForDpn invalid srcDpnId {}, srcTepIp {}, destTepIp {}", srcDpnId, srcTepIp, destTepIp);
return;
}
int tunTypeVal = getTunnelType(stateTunnelList);
LOG.trace("hndlTepEvntsForDpn : tunTypeVal is {}", tunTypeVal);
String srcTepId = stateTunnelList.getSrcInfo().getTepDeviceId() != null ? stateTunnelList.getSrcInfo().getTepDeviceId() : "0";
String tunnelType = stateTunnelList.getTransportType() != null ? stateTunnelList.getTransportType().toString() : null;
String tunnelName = stateTunnelList.getTunnelInterfaceName();
if (tunTypeVal == NatConstants.ITMTunnelLocType.Invalid.getValue() || srcDpnId.equals(Uint64.ZERO) || srcTepIp == null || destTepIp == null) {
LOG.warn("hndlTepEvntsForDpn : Ignoring TEP event {} for the DPN {} " + "since its a INVALID TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and " + "TUNNEL NAME {} ", tunnelAction, srcTepId, tunnelType, srcTepIp, destTepIp, tunnelName);
return;
}
switch(tunnelAction) {
case TUNNEL_EP_ADD:
try {
txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
if (isTunnelInLogicalGroup(stateTunnelList) || !hndlTepAddForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp, tx)) {
LOG.debug("hndlTepEvntsForDpn : Unable to process TEP ADD");
}
}).get();
} catch (InterruptedException | ExecutionException e) {
LOG.error("Error processing tunnel endpoint addition", e);
}
break;
case TUNNEL_EP_DELETE:
// Moved the current implementation logic to NatTepChangeListener.remove()
break;
case TUNNEL_EP_UPDATE:
break;
default:
LOG.warn("hndlTepEvntsForDpn: unknown tunnelAction: {}", tunnelAction);
break;
}
}
use of org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Tunnel in project netvirt by opendaylight.
the class NaptSwitchHA method isNaptSwitchDown.
// TODO Clean up the exception handling
@SuppressWarnings("checkstyle:IllegalCatch")
public boolean isNaptSwitchDown(Routers extRouter, Uint32 routerId, Uint64 dpnId, Uint64 naptSwitch, Uint32 routerVpnId, Collection<String> externalIpCache, boolean isClearBgpRts, TypedReadWriteTransaction<Configuration> confTx) throws ExecutionException, InterruptedException {
externalIpsCache = externalIpCache;
String routerName = extRouter.getRouterName();
if (!naptSwitch.equals(dpnId)) {
LOG.debug("isNaptSwitchDown : DpnId {} is not a naptSwitch {} for Router {}", dpnId, naptSwitch, routerName);
return false;
}
LOG.debug("NaptSwitch {} is down for Router {}", naptSwitch, routerName);
if (routerId == NatConstants.INVALID_ID) {
LOG.error("isNaptSwitchDown : Invalid routerId returned for routerName {}", routerName);
return true;
}
Uuid networkId = extRouter.getNetworkId();
String vpnName = getExtNetworkVpnName(routerName, networkId);
// elect a new NaptSwitch
naptSwitch = naptSwitchSelector.selectNewNAPTSwitch(routerName, Arrays.asList(naptSwitch));
if (natMode == NatMode.Conntrack) {
Routers extRouters = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
natServiceManager.notify(confTx, extRouters, null, dpnId, dpnId, SnatServiceManager.Action.CNT_ROUTER_ALL_SWITCH_DISBL);
if (extRouters.isEnableSnat()) {
natServiceManager.notify(confTx, extRouters, null, dpnId, dpnId, SnatServiceManager.Action.SNAT_ALL_SWITCH_DISBL);
}
natServiceManager.notify(confTx, extRouters, null, naptSwitch, naptSwitch, SnatServiceManager.Action.CNT_ROUTER_ALL_SWITCH_ENBL);
if (extRouters.isEnableSnat()) {
natServiceManager.notify(confTx, extRouters, null, naptSwitch, naptSwitch, SnatServiceManager.Action.SNAT_ALL_SWITCH_ENBL);
}
} else {
if (naptSwitch.equals(Uint64.ZERO)) {
LOG.warn("isNaptSwitchDown : No napt switch is elected since all the switches for router {}" + " are down. SNAT IS NOT SUPPORTED FOR ROUTER {}", routerName, routerName);
boolean naptUpdatedStatus = updateNaptSwitch(routerName, naptSwitch);
if (!naptUpdatedStatus) {
LOG.debug("isNaptSwitchDown : Failed to update naptSwitch {} for router {} in ds", naptSwitch, routerName);
}
// clearBgpRoutes
if (externalIpsCache != null) {
if (vpnName != null) {
// if (externalIps != null) {
if (isClearBgpRts) {
LOG.debug("isNaptSwitchDown : Clearing both FIB entries and the BGP routes");
for (String externalIp : externalIpsCache) {
externalRouterListener.clearBgpRoutes(externalIp, vpnName);
}
} else {
LOG.debug("isNaptSwitchDown : Clearing the FIB entries but not the BGP routes");
String rd = NatUtil.getVpnRd(dataBroker, vpnName);
for (String externalIp : externalIpsCache) {
LOG.debug("isNaptSwitchDown : Removing Fib entry rd {} prefix {}", rd, externalIp);
fibManager.removeFibEntry(rd, externalIp, null, null);
}
}
} else {
LOG.debug("isNaptSwitchDown : vpn is not associated to extn/w for router {}", routerName);
}
} else {
LOG.debug("isNaptSwitchDown : No ExternalIps found for subnets under router {}, " + "no bgp routes need to be cleared", routerName);
}
return true;
}
// checking elected switch health status
if (!NatUtil.getSwitchStatus(dataBroker, naptSwitch)) {
LOG.error("isNaptSwitchDown : Newly elected Napt switch {} for router {} is down", naptSwitch, routerName);
return true;
}
LOG.debug("isNaptSwitchDown : New NaptSwitch {} is up for Router {} and can proceed for flow installation", naptSwitch, routerName);
// update napt model for new napt switch
boolean naptUpdated = updateNaptSwitch(routerName, naptSwitch);
if (naptUpdated) {
// update group of ordinary switch point to naptSwitch tunnel port
updateNaptSwitchBucketStatus(routerName, routerId, naptSwitch);
} else {
LOG.error("isNaptSwitchDown : Failed to update naptSwitch model for newNaptSwitch {} for router {}", naptSwitch, routerName);
}
// update table26 forward packets to table46(outbound napt table)
FlowEntity flowEntity = buildSnatFlowEntityForNaptSwitch(naptSwitch, routerName, routerVpnId, NatConstants.ADD_FLOW);
if (flowEntity == null) {
LOG.error("isNaptSwitchDown : Failed to populate flowentity for router {} in naptSwitch {}", routerName, naptSwitch);
} else {
LOG.debug("isNaptSwitchDown : Successfully installed flow in naptSwitch {} for router {}", naptSwitch, routerName);
mdsalManager.addFlow(confTx, flowEntity);
}
installSnatFlows(routerName, routerId, naptSwitch, routerVpnId, networkId, vpnName, confTx);
boolean flowInstalledStatus = handleNatFlowsInNewNaptSwitch(routerName, routerId, dpnId, naptSwitch, routerVpnId, networkId);
if (flowInstalledStatus) {
LOG.debug("isNaptSwitchDown :Installed all active session flows in newNaptSwitch {} for routerName {}", naptSwitch, routerName);
} else {
LOG.error("isNaptSwitchDown : Failed to install flows in newNaptSwitch {} for routerId {}", naptSwitch, routerId);
}
// remove group in new naptswitch, coz this switch acted previously as ordinary switch
Uint32 groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME, NatUtil.getGroupIdKey(routerName));
if (groupId != NatConstants.INVALID_ID) {
try {
LOG.info("isNaptSwitchDown : Removing NAPT Group in new naptSwitch {}", naptSwitch);
mdsalManager.removeGroup(confTx, naptSwitch, groupId.longValue());
} catch (Exception ex) {
LOG.error("isNaptSwitchDown : Failed to remove group in new naptSwitch {}", naptSwitch, ex);
}
} else {
LOG.error("NAT Service : Unable to obtain groupId for router:{}", routerName);
}
}
return true;
}
use of org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Tunnel in project netvirt by opendaylight.
the class NaptSwitchHA method getTunnelInterfaceName.
@Nullable
protected String getTunnelInterfaceName(Uint64 srcDpId, Uint64 dstDpId) {
Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
try {
Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder().setSourceDpid(srcDpId).setDestinationDpid(dstDpId).setTunnelType(tunType).build());
rpcResult = result.get();
if (!rpcResult.isSuccessful()) {
tunType = TunnelTypeGre.class;
result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder().setSourceDpid(srcDpId).setDestinationDpid(dstDpId).setTunnelType(tunType).build());
rpcResult = result.get();
if (!rpcResult.isSuccessful()) {
LOG.warn("getTunnelInterfaceName : RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
} else {
return rpcResult.getResult().getInterfaceName();
}
LOG.warn("getTunnelInterfaceName : RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
} else {
return rpcResult.getResult().getInterfaceName();
}
} catch (InterruptedException | ExecutionException e) {
LOG.error("getTunnelInterfaceName :Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstDpId, e);
}
LOG.error("getTunnelInterfaceName : Tunnel missing between dpn {}:{}", srcDpId, dstDpId);
return null;
}
Aggregations