package org.opendaylight.netvirt.natservice.internal;
import com.google.common.base.Optional;
+import com.google.common.base.Strings;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.JdkFutureAdapters;
import com.google.common.util.concurrent.ListenableFuture;
import java.math.BigInteger;
import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.Future;
+import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
import org.opendaylight.genius.mdsalutil.BucketInfo;
import org.opendaylight.genius.mdsalutil.FlowEntity;
import org.opendaylight.genius.mdsalutil.GroupEntity;
import org.opendaylight.netvirt.fibmanager.api.IFibManager;
import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
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.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
private final FloatingIPListener floatingIPListener;
private final FibRpcService fibRpcService;
private final IElanService elanManager;
+ private final IInterfaceManager interfaceManager;
private NatMode natMode = NatMode.Controller;
protected enum TunnelAction {
final FloatingIPListener floatingIPListener,
final FibRpcService fibRpcService,
final NatserviceConfig config,
- final IElanService elanManager) {
+ final IElanService elanManager,
+ final IInterfaceManager interfaceManager) {
super(StateTunnelList.class, NatTunnelInterfaceStateListener.class);
this.dataBroker = dataBroker;
this.bgpManager = bgpManager;
this.floatingIPListener = floatingIPListener;
this.fibRpcService = fibRpcService;
this.elanManager = elanManager;
+ this.interfaceManager = interfaceManager;
if (config != null) {
this.natMode = config.getNatMode();
}
//remove miss entry to NAPT switch
//if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
- //get ExternalIpIn prior
- List<String> externalIpCache;
- //HashMap Label
- HashMap<String, Long> externalIpLabel;
Long routerId = NatUtil.getVpnId(dataBroker, routerName);
if (routerId == NatConstants.INVALID_ID) {
LOG.error("NAT Service : SNAT -> Invalid routerId returned for routerName {}", routerName);
return;
}
- externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
+ Collection<String> externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
ProviderTypes extNwProvType = NatEvpnUtil.getExtNwProvTypeFromRouterName(dataBroker,routerName);
if (extNwProvType == null) {
return;
}
+ Map<String, Long> externalIpLabel;
if (extNwProvType == ProviderTypes.VXLAN) {
externalIpLabel = null;
} else {
GroupEntity groupEntity = null;
try {
groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
- GroupTypes.GroupAll, null);
- LOG.info("NAT Service : SNAT -> Removing NAPT GroupEntity:{}", groupEntity);
+ GroupTypes.GroupAll, Collections.emptyList() /*listBucketInfo*/);
+ LOG.info("NAT Service : SNAT -> Removing NAPT GroupEntity:{} on Dpn {}", groupEntity, dpnId);
mdsalManager.removeGroup(groupEntity);
} catch (Exception ex) {
LOG.debug("NAT Service : SNAT -> Failed to remove group entity {} : {}", groupEntity, ex);
LOG.trace("NAT Service : Handle tunnel event for srcDpn {} SrcTepIp {} DestTepIp {} ", srcDpnId, srcTepIp,
destTepIp);
int tunTypeVal = getTunnelType(stateTunnelList);
-
LOG.trace("NAT Service : tunTypeVal is {}", tunTypeVal);
-
try {
String srcTepId = stateTunnelList.getSrcInfo().getTepDeviceId();
String tunnelType = stateTunnelList.getTransportType().toString();
switch (tunnelAction) {
case TUNNEL_EP_ADD:
- if (!hndlTepAddForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp)) {
+ if (isTunnelInLogicalGroup(stateTunnelList)
+ || !hndlTepAddForAllRtrs(srcDpnId, tunnelType, tunnelName, srcTepIp, destTepIp)) {
LOG.debug("NAT Service : Unable to process TEP ADD");
}
break;
+ " : {} and DEST IP: {}", fibManager.getTransportTypeStr(tunnelType), srcTepIp, destTepIp);
InstanceIdentifier<DpnRoutersList> dpnRoutersListId = NatUtil.getDpnRoutersId(srcDpnId);
- Optional<DpnRoutersList> optionalRouterDpnList = NatUtil.read(dataBroker, LogicalDatastoreType
- .OPERATIONAL, dpnRoutersListId);
+ Optional<DpnRoutersList> optionalRouterDpnList =
+ SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
+ LogicalDatastoreType.OPERATIONAL, dpnRoutersListId);
if (!optionalRouterDpnList.isPresent()) {
LOG.warn("NAT Service : RouterDpnList model is empty for DPN {}. Hence ignoring TEP add event for the ITM "
+ "TUNNEL TYPE {} b/w SRC IP {} and DST IP {} and TUNNEL NAME {} ",
List<RoutersList> routersList = null;
InstanceIdentifier<DpnRoutersList> dpnRoutersListId = NatUtil.getDpnRoutersId(srcDpnId);
- Optional<DpnRoutersList> optionalRouterDpnList = NatUtil.read(dataBroker, LogicalDatastoreType
- .OPERATIONAL, dpnRoutersListId);
+ Optional<DpnRoutersList> optionalRouterDpnList =
+ SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
+ LogicalDatastoreType.OPERATIONAL, dpnRoutersListId);
if (optionalRouterDpnList.isPresent()) {
routersList = optionalRouterDpnList.get().getRoutersList();
} else {
// Check if this is externalRouter else ignore
InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
- Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType
- .CONFIGURATION, extRoutersId);
+ Optional<Routers> routerData =
+ SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
+ LogicalDatastoreType.CONFIGURATION, extRoutersId);
if (!routerData.isPresent()) {
LOG.debug("NAT Service : SNAT -> Ignoring TEP add for router {} since its not External Router",
routerName);
+ "with vpnId {}...", srcDpnId, routerId, vpnId);
defaultRouteProgrammer.installDefNATRouteInDPN(srcDpnId, vpnId, routerId);
- LOG.debug("NAT Service : Install group in non NAPT switch {}", srcDpnId);
+ LOG.debug("NAT Service : Install group in non NAPT switch {} for router {}", srcDpnId, routerName);
List<BucketInfo> bucketInfoForNonNaptSwitches =
- externalRouterListner.getBucketInfoForNonNaptSwitches(srcDpnId, srcDpnId, routerName);
+ externalRouterListner.getBucketInfoForNonNaptSwitches(srcDpnId, primaryDpnId, routerName);
long groupId = externalRouterListner.installGroup(srcDpnId, routerName, bucketInfoForNonNaptSwitches);
LOG.debug("NAT Service : SNAT -> in the SNAT miss entry pointing to group {} in the non NAPT switch {}",
Long vpnId;
if (vpnName == null) {
LOG.debug("NAT Service : SNAT -> Internal VPN associated to router {}", routerId);
- vpnId = NatUtil.getVpnId(dataBroker, routerId);
- if (vpnId == null || vpnId == NatConstants.INVALID_ID) {
+ vpnId = NatUtil.getNetworkVpnIdFromRouterId(dataBroker, routerId);
+ if (vpnId == NatConstants.INVALID_ID) {
LOG.error("Invalid External VPN-ID returned for routerName {}", routerName);
return false;
}
networkId, routerId);
return false;
}
- List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
- if (externalIps != null) {
- LOG.debug("NAT Service : Clearing the FIB entries but not the BGP routes");
- for (String externalIp : externalIps) {
- String rd = NatUtil.getVpnRd(dataBroker, externalVpnName);
- LOG.debug("NAT Service : Removing Fib entry rd {} prefix {}", rd, externalIp);
- fibManager.removeFibEntry(dataBroker, rd, externalIp, null);
- }
+ Collection<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
+ LOG.debug("NAT Service : Clearing the FIB entries but not the BGP routes");
+ for (String externalIp : externalIps) {
+ String rd = NatUtil.getVpnRd(dataBroker, externalVpnName);
+ LOG.debug("NAT Service : Removing Fib entry rd {} prefix {}", rd, externalIp);
+ fibManager.removeFibEntry(dataBroker, rd, externalIp, null);
}
/*
if (extNwProvType == ProviderTypes.VXLAN) {
// Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
gwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
+ if (gwMacAddress != null) {
+ LOG.debug("External Gateway MAC address {} found for External Router ID {}", gwMacAddress,
+ routerId);
+ } else {
+ LOG.error("No External Gateway MAC address found for External Router ID {}", routerId);
+ return false;
+ }
//get l3Vni value for external VPN
l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
if (externalIps != null) {
for (final String externalIp : externalIps) {
long serviceId = 0;
+ String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
if (extNwProvType == ProviderTypes.VXLAN) {
LOG.debug("NAT Service : SNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
externalIp, nextHopIp);
Uuid externalSubnetId = NatUtil.getExternalSubnetForRouterExternalIp(dataBroker, externalIp,
router);
NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, externalVpnName, rd, externalSubnetId,
- externalIp, nextHopIp, networkId.getValue(), null /* mac-address */, label, l3vni, LOG,
+ fibExternalIp, nextHopIp, networkId.getValue(), null /* mac-address */, label, l3vni, LOG,
RouteOrigin.STATIC, srcDpnId);
serviceId = label;
}
.buildInstruction(customInstructionIndex));
CreateFibEntryInput input =
new CreateFibEntryInputBuilder().setVpnName(externalVpnName).setSourceDpid(srcDpnId)
- .setInstruction(customInstructions).setIpAddress(externalIp + "/32")
+ .setInstruction(customInstructions).setIpAddress(fibExternalIp)
.setServiceId(serviceId).setInstruction(customInstructions).build();
Future<RpcResult<Void>> future = fibRpcService.createFibEntry(input);
ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
@Override
- public void onFailure(Throwable error) {
+ public void onFailure(@Nonnull Throwable error) {
LOG.error("NAT Service : SNAT -> Error in generate label or fib install process", error);
}
if (extNwProvType == ProviderTypes.VXLAN) {
// Get the External Gateway MAC Address which is Router gateway MAC address for SNAT
gwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
+ if (gwMacAddress != null) {
+ LOG.debug("External Gateway MAC address {} found for External Router ID {}", gwMacAddress,
+ routerId);
+ } else {
+ LOG.error("No External Gateway MAC address found for External Router ID {}", routerId);
+ return;
+ }
//get l3Vni value for external VPN
l3Vni = NatEvpnUtil.getL3Vni(dataBroker, rd);
if (l3Vni == NatConstants.DEFAULT_L3VNI_VALUE) {
+ "for the port: {}",
externalIp, interfaceName);
long serviceId = 0;
+ String fibExternalIp = NatUtil.validateAndAddNetworkMask(externalIp);
+
if (extNwProvType == ProviderTypes.VXLAN) {
LOG.debug("NAT Service : DNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
externalIp, nextHopIp);
l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, l3vni).longValue();
}
NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd, null,
- externalIp + "/32", nextHopIp, null, null, label, l3vni, LOG, RouteOrigin.STATIC,
+ fibExternalIp, nextHopIp, null, null, label, l3vni, LOG, RouteOrigin.STATIC,
fipCfgdDpnId);
serviceId = label;
}
customInstructions.add(new InstructionGotoTable(NwConstants.PDNAT_TABLE).buildInstruction(0));
CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName)
.setSourceDpid(fipCfgdDpnId).setInstruction(customInstructions)
- .setIpAddress(externalIp + "/32").setServiceId(serviceId).setInstruction(customInstructions)
+ .setIpAddress(fibExternalIp).setServiceId(serviceId).setInstruction(customInstructions)
.build();
Future<RpcResult<Void>> future = fibRpcService.createFibEntry(input);
ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
@Override
- public void onFailure(Throwable error) {
+ public void onFailure(@Nonnull Throwable error) {
LOG.error("NAT Service : DNAT -> Error in generate label or fib install process", error);
}
// Check if this is externalRouter else ignore
InstanceIdentifier<Routers> extRoutersId = NatUtil.buildRouterIdentifier(routerName);
- Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType
- .CONFIGURATION, extRoutersId);
+ Optional<Routers> routerData =
+ SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
+ LogicalDatastoreType.CONFIGURATION, extRoutersId);
if (!routerData.isPresent()) {
LOG.debug("NAT Service : SNAT -> Ignoring TEP del for router {} since its not External Router",
routerName);
for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) {
String internalIp = intExtPortMap.getInternalIp();
String externalIp = intExtPortMap.getExternalIp();
+ externalIp = NatUtil.validateAndAddNetworkMask(externalIp);
LOG.debug("NAT Service : DNAT -> Withdrawing the FIB route to the floating IP {} "
+ "configured for the port: {}",
externalIp, interfaceName);
- NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp + "/32", vpnName, LOG);
+ NatUtil.removePrefixFromBGP(dataBroker, bgpManager, fibManager, rd, externalIp, vpnName, LOG);
long serviceId = 0;
if (extNwProvType == ProviderTypes.VXLAN) {
serviceId = l3Vni;
}
serviceId = label;
}
+
RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName)
- .setSourceDpid(fipCfgdDpnId).setIpAddress(externalIp + "/32").setServiceId(serviceId).build();
+ .setSourceDpid(fipCfgdDpnId).setIpAddress(externalIp).setServiceId(serviceId)
+ .setIpAddressSource(RemoveFibEntryInput.IpAddressSource.FloatingIP).build();
Future<RpcResult<Void>> future = fibRpcService.removeFibEntry(input);
ListenableFuture<RpcResult<Void>> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
Futures.addCallback(listenableFuture, new FutureCallback<RpcResult<Void>>() {
@Override
- public void onFailure(Throwable error) {
+ public void onFailure(@Nonnull Throwable error) {
LOG.error("NAT Service : DNAT -> Error in removing the table 21 entry pushing "
+ "the MPLS label to the tunnel since label is invalid ", error);
}
}
}
}
+
+ protected boolean isTunnelInLogicalGroup(StateTunnelList stateTunnelList) {
+ String ifaceName = stateTunnelList.getTunnelInterfaceName();
+ if (getTunnelType(stateTunnelList) == NatConstants.ITMTunnelLocType.Internal.getValue()) {
+ Interface configIface = interfaceManager.getInterfaceInfoFromConfigDataStore(ifaceName);
+ IfTunnel ifTunnel = (configIface != null) ? configIface.getAugmentation(IfTunnel.class) : null;
+ if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
+ ParentRefs refs = configIface.getAugmentation(ParentRefs.class);
+ if (refs != null && !Strings.isNullOrEmpty(refs.getParentInterface())) {
+ return true; //multiple VxLAN tunnels enabled, i.e. only logical tunnel should be treated
+ }
+ }
+ }
+ LOG.trace("MULTIPLE_VxLAN_TUNNELS: ignoring the tunnel event for {}", ifaceName);
+ return false;
+ }
}