/* * Copyright © 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, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.netvirt.natservice.rpcservice; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; import org.opendaylight.genius.mdsalutil.NwConstants; import org.opendaylight.mdsal.binding.api.DataBroker; import org.opendaylight.netvirt.natservice.internal.NatConstants; import org.opendaylight.netvirt.natservice.internal.NatUtil; import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager; 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.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsForNetworkAndIpaddressInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsForNetworkAndIpaddressOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsForNetworkAndIpaddressOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnRouterInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnRouterOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnRouterOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnVpnInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnVpnOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnVpnOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.OdlNatRpcService; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.dnat.configuration.DnatIpMapping; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.dnat.configuration.DnatIpMappingBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.nat.output.RouterNat; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.nat.output.RouterNatBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.snat.state.SnatIpMapping; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.snat.state.SnatIpMappingBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnet.attributes.AllocationPools; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet; import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.opendaylight.yangtools.yang.common.Uint32; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Singleton public class NatRpcServiceImpl implements OdlNatRpcService { private static final Logger LOG = LoggerFactory.getLogger(NatRpcServiceImpl.class); private final DataBroker dataBroker; private final INeutronVpnManager nvpnManager; @Inject public NatRpcServiceImpl(final DataBroker dataBroker, final INeutronVpnManager nvpnManager) { this.dataBroker = dataBroker; this.nvpnManager = nvpnManager; } @Override public ListenableFuture> getNatTranslationsOnVpn( GetNatTranslationsOnVpnInput input) { RpcResultBuilder rpcResultBuilder = null; List routerUuidList = NatUtil.getRouterUuIdsForVpn(dataBroker, input.getVpnUuid()); if (routerUuidList.isEmpty()) { String errMsg = String.format("404 Not Found - Invalid external vpn {%s} provided", input.getVpnUuid().getValue()); rpcResultBuilder = RpcResultBuilder.failed() .withError(RpcError.ErrorType.APPLICATION, errMsg); return rpcResultBuilder.buildFuture(); } List natRouterList = new ArrayList<>(); for (Uuid routerUuid : routerUuidList) { Uint32 routerId = NatUtil.getVpnId(dataBroker, routerUuid.getValue()); if (routerId == NatConstants.INVALID_ID) { LOG.warn("getNatTranslationsOnVpn : Invalid RouterID found {}", routerId); continue; } natRouterList.addAll(constructNatInformation(routerUuid, routerId)); } GetNatTranslationsOnVpnOutputBuilder output = new GetNatTranslationsOnVpnOutputBuilder() .setRouterNat(natRouterList); rpcResultBuilder = RpcResultBuilder.success(); rpcResultBuilder.withResult(output.build()); return Futures.immediateFuture(rpcResultBuilder.build()); } @Override public ListenableFuture> getNatTranslationsOnRouter( GetNatTranslationsOnRouterInput input) { RpcResultBuilder rpcResultBuilder = null; Uint32 routerId = NatUtil.getVpnId(dataBroker, input.getRouterUuid().getValue()); if (routerId == NatConstants.INVALID_ID) { String errMsg = String.format("404 Not Found - No Router found with UUID {%s}", input.getRouterUuid().getValue()); rpcResultBuilder = RpcResultBuilder.failed() .withError(RpcError.ErrorType.APPLICATION, errMsg); return rpcResultBuilder.buildFuture(); } List routerNatList = constructNatInformation(input.getRouterUuid(), routerId); GetNatTranslationsOnRouterOutputBuilder output = new GetNatTranslationsOnRouterOutputBuilder() .setRouterNat(routerNatList); rpcResultBuilder = RpcResultBuilder.success(); rpcResultBuilder.withResult(output.build()); return rpcResultBuilder.buildFuture(); } @Override public ListenableFuture> getNatTranslationsForNetworkAndIpaddress(GetNatTranslationsForNetworkAndIpaddressInput input) { String ipAddress = input.getIpAddress().stringValue(); RpcResultBuilder rpcResultBuilder = null; GetNatTranslationsForNetworkAndIpaddressOutputBuilder output = null; List subnetUuidList = NatUtil.getSubnetIdsFromNetworkId(dataBroker, input.getNetworkUuid()); if (subnetUuidList.isEmpty()) { String errMsg = String.format("404 Not Found - Invalid Network UUID {%s} provided as no Subnetworks found", input.getNetworkUuid().getValue()); rpcResultBuilder = RpcResultBuilder.failed() .withError(RpcError.ErrorType.APPLICATION, errMsg); return rpcResultBuilder.buildFuture(); } Subnet subNet = null; Boolean isIpInSubnet = Boolean.FALSE; outerloop: for (Uuid subnetUuid: subnetUuidList) { subNet = nvpnManager.getNeutronSubnet(subnetUuid); for (AllocationPools allocationPool : subNet.nonnullAllocationPools()) { if (NatUtil.isIpInSubnet(ipAddress, allocationPool.getStart().stringValue(), allocationPool.getEnd().stringValue())) { LOG.debug("getNatTranslationsForNetworkAndIpaddress : IP Adderess {} falls within the Subnet {}", ipAddress, subNet.getUuid().getValue()); isIpInSubnet = Boolean.TRUE; break outerloop; } } } if (!isIpInSubnet) { String errMsg = String.format("404 Not Found - IP Adress {%s} does not fall within the Subnet IP range" + " of Network {%s}", ipAddress, input.getNetworkUuid().getValue()); rpcResultBuilder = RpcResultBuilder.failed() .withError(RpcError.ErrorType.APPLICATION, errMsg); return rpcResultBuilder.buildFuture(); } Subnetmap subnetMap = NatUtil.getSubnetMap(dataBroker, subNet.getUuid()); Uint32 routerId = NatUtil.getVpnId(dataBroker, subnetMap.getRouterId().getValue()); List fipPorts = NatUtil.getFloatingIpPortsForRouter(dataBroker, subnetMap.getRouterId()); if (fipPorts.isEmpty()) { LOG.warn("getNatTranslationsForNetworkAndIpaddress : No DNAT IP Mapping found for IP {}", ipAddress); } else { for (Ports fipPort : fipPorts) { for (InternalToExternalPortMap fipMap : fipPort.nonnullInternalToExternalPortMap()) { if (fipMap.getInternalIp().equals(ipAddress)) { output = new GetNatTranslationsForNetworkAndIpaddressOutputBuilder() .setExternalIp(fipMap.getExternalIp()) .setNatTranslation("DNAT"); rpcResultBuilder = RpcResultBuilder.success(); rpcResultBuilder.withResult(output.build()); return rpcResultBuilder.buildFuture(); } } } } IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId); if (ipPortMapping == null) { LOG.warn("getNatTranslationsForNetworkAndIpaddress : No SNAT IP Mapping found for IP {}", ipAddress); } else { for (IntextIpProtocolType protocolType : ipPortMapping.nonnullIntextIpProtocolType()) { for (IpPortMap ipPortMap : protocolType.nonnullIpPortMap()) { String[] internalIpPort = ipPortMap.getIpPortInternal().split(NwConstants.MACADDR_SEP); if (ipAddress.equals(internalIpPort[0])) { output = new GetNatTranslationsForNetworkAndIpaddressOutputBuilder() .setExternalIp(ipPortMap.getIpPortExternal().getIpAddress()) .setInternalIp(internalIpPort[0]) .setNatTranslation("SNAT") .setInternalPort(internalIpPort[1]) .setExternalPort(ipPortMap.getIpPortExternal().getPortNum().toString()) .setProtocol(protocolType.getProtocol().getName()); rpcResultBuilder = RpcResultBuilder.success(); rpcResultBuilder.withResult(output.build()); return rpcResultBuilder.buildFuture(); } } } } String errMsg = String.format("404 Not Found - No NAT Translation found for IP {%s}", ipAddress); rpcResultBuilder = RpcResultBuilder.failed() .withError(RpcError.ErrorType.APPLICATION, errMsg); return rpcResultBuilder.buildFuture(); } private List constructNatInformation(Uuid routerUuid, Uint32 routerId) { String neutronRouterName = NatUtil.getNeutronRouterNamebyUuid(dataBroker, routerUuid); RouterNatBuilder natRouterBuilder = new RouterNatBuilder(); natRouterBuilder.setRouterUuid(routerUuid); natRouterBuilder.setRouterName(neutronRouterName); IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId); if (ipPortMapping == null) { LOG.warn("constructNatInformation : No SNAT IP Mapping found for router-uuid {}", routerUuid.getValue()); } else { // Capturing SNAT information List snatIpMapping = new ArrayList<>(); for (IntextIpProtocolType protocolType : ipPortMapping.nonnullIntextIpProtocolType()) { for (IpPortMap ipPortMap : protocolType.nonnullIpPortMap()) { String[] internalPortMap = ipPortMap.getIpPortInternal().split(NwConstants.MACADDR_SEP); SnatIpMappingBuilder natIpMappingBuilder = new SnatIpMappingBuilder() .setInternalIp(internalPortMap[0]).setInternalPort(internalPortMap[1]) .setExternalIp(ipPortMap.getIpPortExternal().getIpAddress()) .setExternalPort(ipPortMap.getIpPortExternal().getPortNum().toString()) .setProtocol(protocolType.getProtocol().getName()); snatIpMapping.add(natIpMappingBuilder.build()); } } natRouterBuilder.setSnatIpMapping(snatIpMapping); } // Capturing DNAT information List dnatIpMapping = new ArrayList<>(); List fipPorts = NatUtil.getFloatingIpPortsForRouter(dataBroker, routerUuid); if (fipPorts.isEmpty()) { LOG.warn("constructNatInformation : No DNAT IP Mapping found for router-uuid {}", routerUuid.getValue()); } else { for (Ports fipPort : fipPorts) { for (InternalToExternalPortMap fipMap : fipPort.nonnullInternalToExternalPortMap()) { DnatIpMappingBuilder natIpMappingBuilder = new DnatIpMappingBuilder() .setExternalIp(fipMap.getExternalIp()).setInternalIp(fipMap.getInternalIp()); dnatIpMapping.add(natIpMappingBuilder.build()); } } natRouterBuilder.setDnatIpMapping(dnatIpMapping); } List natRouterList = new ArrayList<>(); natRouterList.add(natRouterBuilder.build()); return natRouterList; } }