2 * Copyright © 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.natservice.rpcservice;
10 import com.google.common.util.concurrent.Futures;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.concurrent.Future;
16 import javax.inject.Inject;
17 import javax.inject.Singleton;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.genius.mdsalutil.NwConstants;
20 import org.opendaylight.netvirt.natservice.internal.NatConstants;
21 import org.opendaylight.netvirt.natservice.internal.NatUtil;
22 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsForNetworkAndIpaddressInput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsForNetworkAndIpaddressOutput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsForNetworkAndIpaddressOutputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnRouterInput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnRouterOutput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnRouterOutputBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnVpnInput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnVpnOutput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnVpnOutputBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.OdlNatRpcService;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.dnat.configuration.DnatIpMapping;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.dnat.configuration.DnatIpMappingBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.nat.output.RouterNat;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.nat.output.RouterNatBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.snat.state.SnatIpMapping;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.snat.state.SnatIpMappingBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnet.attributes.AllocationPools;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
48 import org.opendaylight.yangtools.yang.common.RpcError;
49 import org.opendaylight.yangtools.yang.common.RpcResult;
50 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
56 public class NatRpcServiceImpl implements OdlNatRpcService {
58 private static final Logger LOG = LoggerFactory.getLogger(NatRpcServiceImpl.class);
59 private final DataBroker dataBroker;
60 private final INeutronVpnManager nvpnManager;
63 public NatRpcServiceImpl(final DataBroker dataBroker, final INeutronVpnManager nvpnManager) {
64 this.dataBroker = dataBroker;
65 this.nvpnManager = nvpnManager;
69 public Future<RpcResult<GetNatTranslationsOnVpnOutput>> getNatTranslationsOnVpn(
70 GetNatTranslationsOnVpnInput input) {
71 RpcResultBuilder<GetNatTranslationsOnVpnOutput> rpcResultBuilder = null;
73 List<Uuid> routerUuidList = NatUtil.getRouterUuIdsForVpn(dataBroker, input.getVpnUuid());
74 if (routerUuidList.isEmpty()) {
75 String errMsg = String.format("404 Not Found - Invalid external vpn {%s} provided",
76 input.getVpnUuid().getValue());
77 rpcResultBuilder = RpcResultBuilder.<GetNatTranslationsOnVpnOutput>failed()
78 .withError(RpcError.ErrorType.APPLICATION, errMsg);
79 return Futures.immediateFuture(rpcResultBuilder.build());
81 List<RouterNat> natRouterList = new ArrayList<>();
82 for (Uuid routerUuid : routerUuidList) {
83 long routerId = NatUtil.getVpnId(dataBroker, routerUuid.getValue());
84 if (routerId == NatConstants.INVALID_ID) {
85 LOG.warn("getNatTranslationsOnVpn : Invalid RouterID found {}", routerId);
88 natRouterList.addAll(constructNatInformation(routerUuid, routerId));
90 GetNatTranslationsOnVpnOutputBuilder output = new GetNatTranslationsOnVpnOutputBuilder()
91 .setRouterNat(natRouterList);
92 rpcResultBuilder = RpcResultBuilder.success();
93 rpcResultBuilder.withResult(output.build());
94 return Futures.immediateFuture(rpcResultBuilder.build());
98 public Future<RpcResult<GetNatTranslationsOnRouterOutput>> getNatTranslationsOnRouter(
99 GetNatTranslationsOnRouterInput input) {
100 RpcResultBuilder<GetNatTranslationsOnRouterOutput> rpcResultBuilder = null;
101 long routerId = NatUtil.getVpnId(dataBroker, input.getRouterUuid().getValue());
102 if (routerId == NatConstants.INVALID_ID) {
103 String errMsg = String.format("404 Not Found - No Router found with UUID {%s}",
104 input.getRouterUuid().getValue());
105 rpcResultBuilder = RpcResultBuilder.<GetNatTranslationsOnRouterOutput>failed()
106 .withError(RpcError.ErrorType.APPLICATION, errMsg);
107 return Futures.immediateFuture(rpcResultBuilder.build());
110 List<RouterNat> routerNatList = constructNatInformation(input.getRouterUuid(), routerId);
112 GetNatTranslationsOnRouterOutputBuilder output = new GetNatTranslationsOnRouterOutputBuilder()
113 .setRouterNat(routerNatList);
114 rpcResultBuilder = RpcResultBuilder.success();
115 rpcResultBuilder.withResult(output.build());
116 return Futures.immediateFuture(rpcResultBuilder.build());
119 public Future<RpcResult<GetNatTranslationsForNetworkAndIpaddressOutput>> getNatTranslationsForNetworkAndIpaddress(
120 GetNatTranslationsForNetworkAndIpaddressInput input) {
122 String ipAddress = String.valueOf(input.getIpAddress().getValue());
123 RpcResultBuilder<GetNatTranslationsForNetworkAndIpaddressOutput> rpcResultBuilder = null;
124 GetNatTranslationsForNetworkAndIpaddressOutputBuilder output = null;
126 List<Uuid> subnetUuidList = NatUtil.getSubnetIdsFromNetworkId(dataBroker, input.getNetworkUuid());
127 if (subnetUuidList.isEmpty()) {
128 String errMsg = String.format("404 Not Found - Invalid Network UUID {%s} provided as no Subnetworks found",
129 input.getNetworkUuid().getValue());
130 rpcResultBuilder = RpcResultBuilder.<GetNatTranslationsForNetworkAndIpaddressOutput>failed()
131 .withError(RpcError.ErrorType.APPLICATION, errMsg);
132 return Futures.immediateFuture(rpcResultBuilder.build());
134 Subnet subNet = null;
135 Boolean isIpInSubnet = Boolean.FALSE;
137 for (Uuid subnetUuid: subnetUuidList) {
138 subNet = nvpnManager.getNeutronSubnet(subnetUuid);
139 for (AllocationPools allocationPool : subNet.getAllocationPools()) {
140 if (NatUtil.isIpInSubnet(ipAddress,
141 String.valueOf(allocationPool.getStart().getValue()),
142 String.valueOf(allocationPool.getEnd().getValue()))) {
143 LOG.debug("getNatTranslationsForNetworkAndIpaddress : IP Adderess {} falls within the Subnet {}",
144 ipAddress, subNet.getUuid().getValue());
145 isIpInSubnet = Boolean.TRUE;
152 String errMsg = String.format("404 Not Found - IP Adress {%s} does not fall within the Subnet IP range"
153 + " of Network {%s}", ipAddress, input.getNetworkUuid().getValue());
154 rpcResultBuilder = RpcResultBuilder.<GetNatTranslationsForNetworkAndIpaddressOutput>failed()
155 .withError(RpcError.ErrorType.APPLICATION, errMsg);
156 return Futures.immediateFuture(rpcResultBuilder.build());
159 Subnetmap subnetMap = NatUtil.getSubnetMap(dataBroker, subNet.getUuid());
160 long routerId = NatUtil.getVpnId(dataBroker, subnetMap.getRouterId().getValue());
162 List<Ports> fipPorts = NatUtil.getFloatingIpPortsForRouter(dataBroker, subnetMap.getRouterId());
163 if (fipPorts.isEmpty()) {
164 LOG.warn("getNatTranslationsForNetworkAndIpaddress : No DNAT IP Mapping found for IP {}", ipAddress);
166 for (Ports fipPort : fipPorts) {
167 List<InternalToExternalPortMap> ipMapping = fipPort.getInternalToExternalPortMap();
168 for (InternalToExternalPortMap fipMap : ipMapping) {
169 if (fipMap.getInternalIp().equals(ipAddress)) {
170 output = new GetNatTranslationsForNetworkAndIpaddressOutputBuilder()
171 .setExternalIp(fipMap.getExternalIp())
172 .setNatTranslation("DNAT");
173 rpcResultBuilder = RpcResultBuilder.success();
174 rpcResultBuilder.withResult(output.build());
175 return Futures.immediateFuture(rpcResultBuilder.build());
181 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
182 if (ipPortMapping == null) {
183 LOG.warn("getNatTranslationsForNetworkAndIpaddress : No SNAT IP Mapping found for IP {}", ipAddress);
185 for (IntextIpProtocolType protocolType : ipPortMapping.getIntextIpProtocolType()) {
186 for (IpPortMap ipPortMap : protocolType.getIpPortMap()) {
187 String[] internalIpPort = ipPortMap.getIpPortInternal().split(NwConstants.MACADDR_SEP);
188 if (ipAddress.equals(internalIpPort[0])) {
190 output = new GetNatTranslationsForNetworkAndIpaddressOutputBuilder()
191 .setExternalIp(ipPortMap.getIpPortExternal().getIpAddress())
192 .setInternalIp(internalIpPort[0])
193 .setNatTranslation("SNAT")
194 .setInternalPort(internalIpPort[1])
195 .setExternalPort(ipPortMap.getIpPortExternal().getPortNum().toString())
196 .setProtocol(protocolType.getProtocol().getName());
197 rpcResultBuilder = RpcResultBuilder.success();
198 rpcResultBuilder.withResult(output.build());
199 return Futures.immediateFuture(rpcResultBuilder.build());
205 String errMsg = String.format("404 Not Found - No NAT Translation found for IP {%s}", ipAddress);
206 rpcResultBuilder = RpcResultBuilder.<GetNatTranslationsForNetworkAndIpaddressOutput>failed()
207 .withError(RpcError.ErrorType.APPLICATION, errMsg);
208 return Futures.immediateFuture(rpcResultBuilder.build());
211 private List<RouterNat> constructNatInformation(Uuid routerUuid, long routerId) {
213 String neutronRouterName = NatUtil.getNeutronRouterNamebyUuid(dataBroker, routerUuid);
215 RouterNatBuilder natRouterBuilder = new RouterNatBuilder();
216 natRouterBuilder.setRouterUuid(routerUuid);
217 natRouterBuilder.setRouterName(neutronRouterName);
219 IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
220 if (ipPortMapping == null) {
221 LOG.warn("constructNatInformation : No SNAT IP Mapping found for router-uuid {}", routerUuid.getValue());
224 // Capturing SNAT information
225 List<SnatIpMapping> snatIpMapping = new ArrayList<>();
227 for (IntextIpProtocolType protocolType : ipPortMapping.getIntextIpProtocolType()) {
228 for (IpPortMap ipPortMap : protocolType.getIpPortMap()) {
229 String[] internalPortMap = ipPortMap.getIpPortInternal().split(NwConstants.MACADDR_SEP);
230 SnatIpMappingBuilder natIpMappingBuilder = new SnatIpMappingBuilder()
231 .setInternalIp(internalPortMap[0]).setInternalPort(internalPortMap[1])
232 .setExternalIp(ipPortMap.getIpPortExternal().getIpAddress())
233 .setExternalPort(ipPortMap.getIpPortExternal().getPortNum().toString())
234 .setProtocol(protocolType.getProtocol().getName());
235 snatIpMapping.add(natIpMappingBuilder.build());
238 natRouterBuilder.setSnatIpMapping(snatIpMapping);
241 // Capturing DNAT information
242 List<DnatIpMapping> dnatIpMapping = new ArrayList<>();
243 List<Ports> fipPorts = NatUtil.getFloatingIpPortsForRouter(dataBroker, routerUuid);
244 if (fipPorts.isEmpty()) {
245 LOG.warn("constructNatInformation : No DNAT IP Mapping found for router-uuid {}", routerUuid.getValue());
247 for (Ports fipPort : fipPorts) {
248 List<InternalToExternalPortMap> ipMapping = fipPort.getInternalToExternalPortMap();
249 for (InternalToExternalPortMap fipMap : ipMapping) {
250 DnatIpMappingBuilder natIpMappingBuilder = new DnatIpMappingBuilder()
251 .setExternalIp(fipMap.getExternalIp()).setInternalIp(fipMap.getInternalIp());
252 dnatIpMapping.add(natIpMappingBuilder.build());
255 natRouterBuilder.setDnatIpMapping(dnatIpMapping);
258 List<RouterNat> natRouterList = new ArrayList<>();
259 natRouterList.add(natRouterBuilder.build());
260 return natRouterList;