2 * Copyright © 2016, 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
10 * Created eyugsar 2016/12/1
12 package org.opendaylight.netvirt.natservice.internal;
14 import com.google.common.base.Optional;
15 import com.google.common.util.concurrent.UncheckedExecutionException;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.concurrent.ExecutionException;
21 import java.util.concurrent.Future;
22 import javax.annotation.Nonnull;
23 import javax.inject.Inject;
24 import javax.inject.Singleton;
25 import org.apache.commons.net.util.SubnetUtils;
26 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
30 import org.opendaylight.genius.mdsalutil.MDSALUtil;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInputBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpMap;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.SnatintIpPortMap;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCountersKey;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounterBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounterKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMappingKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolTypeKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternalBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMap;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMapKey;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPortKey;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeKey;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
75 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
76 import org.opendaylight.yangtools.yang.common.RpcResult;
77 import org.slf4j.Logger;
78 import org.slf4j.LoggerFactory;
81 public class NaptManager {
82 private static final Logger LOG = LoggerFactory.getLogger(NaptManager.class);
83 private final DataBroker dataBroker;
84 private final IdManagerService idManager;
85 private static final long LOW_PORT = 49152L;
86 private static final long HIGH_PORT = 65535L;
87 private static boolean EXTSUBNET_FLAG = false;
88 private static boolean NEXT_EXTIP_FLAG = false;
91 public NaptManager(final DataBroker dataBroker, final IdManagerService idManager) {
92 this.dataBroker = dataBroker;
93 this.idManager = idManager;
96 protected void createNaptPortPool(String poolName) {
97 LOG.debug("createNaptPortPool : requested for : {}", poolName);
98 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
99 .setPoolName(poolName)
104 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
105 if ((result != null) && (result.get().isSuccessful())) {
106 LOG.debug("createNaptPortPool : Created PortPool :{}", poolName);
108 LOG.error("createNaptPortPool : Unable to create PortPool : {}", poolName);
110 } catch (InterruptedException | ExecutionException e) {
111 LOG.error("createNaptPortPool : Failed to create PortPool for NAPT Service", e);
115 void removeNaptPortPool(String poolName) {
116 DeleteIdPoolInput deleteIdPoolInput = new DeleteIdPoolInputBuilder().setPoolName(poolName).build();
117 LOG.debug("removeNaptPortPool : Remove Napt port pool requested for : {}", poolName);
119 Future<RpcResult<Void>> result = idManager.deleteIdPool(deleteIdPoolInput);
120 if ((result != null) && (result.get().isSuccessful())) {
121 LOG.debug("removeNaptPortPool : Deleted PortPool {}", poolName);
123 LOG.error("removeNaptPortPool : Unable to delete PortPool {}", poolName);
125 } catch (InterruptedException | ExecutionException e) {
126 LOG.error("removeNaptPortPool : Failed to delete PortPool {} for NAPT Service", poolName, e);
130 // 1. napt service functions
133 * This method is used to inform this service of what external IP address to be used
134 * as mapping when requested one for the internal IP address given in the input.
136 * @param segmentId – segmentation in which the mapping to be used. Eg; routerid
137 * @param internal subnet prefix or ip address
138 * @param external subnet prefix or ip address
141 public void registerMapping(long segmentId, IPAddress internal, IPAddress external) {
142 LOG.debug("registerMapping : called with segmentid {}, internalIp {}, prefix {}, externalIp {} "
143 + "and prefix {} ", segmentId, internal.getIpAddress(),
144 internal.getPrefixLength(), external.getIpAddress(), external.getPrefixLength());
145 // Create Pool per ExternalIp and not for all IPs in the subnet.
146 // Create new Pools during getExternalAddressMapping if exhausted.
147 String externalIpPool;
149 if (external.getPrefixLength() != 0 && external.getPrefixLength() != NatConstants.DEFAULT_PREFIX) {
150 String externalSubnet = external.getIpAddress() + "/" + external.getPrefixLength();
151 LOG.debug("registerMapping : externalSubnet is : {}", externalSubnet);
152 SubnetUtils subnetUtils = new SubnetUtils(externalSubnet);
153 SubnetInfo subnetInfo = subnetUtils.getInfo();
154 externalIpPool = subnetInfo.getLowAddress();
156 externalIpPool = external.getIpAddress();
158 createNaptPortPool(externalIpPool);
160 // Store the ip to ip map in Operational DS
161 String internalIp = internal.getIpAddress();
162 if (internal.getPrefixLength() != 0) {
163 internalIp = internal.getIpAddress() + "/" + internal.getPrefixLength();
165 String externalIp = external.getIpAddress();
166 if (external.getPrefixLength() != 0) {
167 externalIp = external.getIpAddress() + "/" + external.getPrefixLength();
169 updateCounter(segmentId, externalIp, true);
170 //update the actual ip-map
171 IpMap ipm = new IpMapBuilder().setKey(new IpMapKey(internalIp)).setInternalIp(internalIp)
172 .setExternalIp(externalIp).build();
173 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
174 getIpMapIdentifier(segmentId, internalIp), ipm);
175 LOG.debug("registerMapping : registerMapping exit after updating DS with internalIP {}, externalIP {}",
176 internalIp, externalIp);
179 public void updateCounter(long segmentId, String externalIp, boolean isAdd) {
181 InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class)
182 .child(ExternalCounters.class, new ExternalCountersKey(segmentId))
183 .child(ExternalIpCounter.class, new ExternalIpCounterKey(externalIp)).build();
184 Optional<ExternalIpCounter> externalIpCounter =
185 MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
186 if (externalIpCounter.isPresent()) {
187 counter = externalIpCounter.get().getCounter();
190 LOG.debug("updateCounter : externalIp and counter after increment are {} and {}", externalIp, counter);
195 LOG.debug("updateCounter : externalIp and counter after decrement are {} and {}", externalIp, counter);
202 //update the new counter value for this externalIp
203 ExternalIpCounter externalIpCounterData = new ExternalIpCounterBuilder()
204 .setKey(new ExternalIpCounterKey(externalIp)).setExternalIp(externalIp).setCounter(counter).build();
205 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
206 getExternalIpsIdentifier(segmentId, externalIp), externalIpCounterData);
210 * method to get external ip/port mapping when provided with internal ip/port pair
211 * If already a mapping exist for the given input, then the existing mapping is returned
212 * instead of overwriting with new ip/port pair.
214 * @param segmentId - Router ID
215 * @param sourceAddress - internal ip address/port pair
216 * @param protocol - TCP/UDP
217 * @return external ip address/port
219 // TODO Clean up the exception handling
220 @SuppressWarnings("checkstyle:IllegalCatch")
221 public SessionAddress getExternalAddressMapping(long segmentId, SessionAddress sourceAddress,
222 NAPTEntryEvent.Protocol protocol) {
223 LOG.debug("getExternalAddressMapping : called with segmentId {}, internalIp {} and port {}",
224 segmentId, sourceAddress.getIpAddress(), sourceAddress.getPortNumber());
226 1. Get Internal IP, Port in IP:Port format
227 2. Inside DB with routerId get the list of entries and check if it matches with existing IP:Port
228 3. If True return SessionAddress of ExternalIp and Port
229 4. Else check ip Map and Form the ExternalIp and Port and update DB and then return ExternalIp and Port
232 //SessionAddress externalIpPort = new SessionAddress();
233 String internalIpPort = sourceAddress.getIpAddress() + ":" + sourceAddress.getPortNumber();
235 // First check existing Port Map.
236 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
237 if (existingIpPort != null) {
238 // populate externalIpPort from IpPortMap and return
239 LOG.debug("getExternalAddressMapping : successfully returning existingIpPort as {} and {}",
240 existingIpPort.getIpAddress(), existingIpPort.getPortNumber());
241 return existingIpPort;
243 // Now check in ip-map
244 String externalIp = checkIpMap(segmentId, sourceAddress.getIpAddress());
245 if (externalIp == null) {
246 LOG.error("getExternalAddressMapping : Unexpected error, internal to external "
247 + "ip map does not exist");
250 /* Logic assuming internalIp is always ip and not subnet
251 * case 1: externalIp is ip
252 * a) goto externalIp pool and getPort and return
253 * b) else return error
254 * case 2: externalIp is subnet
255 * a) Take first externalIp and goto that Pool and getPort
257 * else Take second externalIp and create that Pool and getPort
260 * Continue same with third externalIp till we exhaust subnet
261 * b) Nothing worked return error
263 SubnetUtils externalIpSubnet;
264 List<String> allIps = new ArrayList<>();
265 String subnetPrefix = "/" + String.valueOf(NatConstants.DEFAULT_PREFIX);
266 if (!externalIp.contains(subnetPrefix)) {
267 EXTSUBNET_FLAG = true;
268 externalIpSubnet = new SubnetUtils(externalIp);
269 allIps = Arrays.asList(externalIpSubnet.getInfo().getAllAddresses());
270 LOG.debug("getExternalAddressMapping : total count of externalIps available {}",
271 externalIpSubnet.getInfo().getAddressCount());
273 LOG.debug("getExternalAddressMapping : getExternalAddress single ip case");
274 if (externalIp.contains(subnetPrefix)) {
275 //remove /32 what we got from checkIpMap
276 externalIp = externalIp.substring(0, externalIp.indexOf(subnetPrefix));
278 allIps.add(externalIp);
281 for (String extIp : allIps) {
282 LOG.info("getExternalAddressMapping : Looping externalIPs with externalIP now as {}", extIp);
283 if (NEXT_EXTIP_FLAG) {
284 createNaptPortPool(extIp);
285 LOG.debug("getExternalAddressMapping : Created Pool for next Ext IP {}", extIp);
287 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
288 .setPoolName(extIp).setIdKey(internalIpPort)
291 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
292 RpcResult<AllocateIdOutput> rpcResult;
293 if ((result != null) && (result.get().isSuccessful())) {
294 LOG.debug("getExternalAddressMapping : Got id from idManager");
295 rpcResult = result.get();
297 LOG.error("getExternalAddressMapping : getExternalAddressMapping, idManager could not "
298 + "allocate id retry if subnet");
299 if (!EXTSUBNET_FLAG) {
300 LOG.error("getExternalAddressMapping : getExternalAddressMapping returning null "
301 + "for single IP case, may be ports exhausted");
304 LOG.debug("getExternalAddressMapping : Could be ports exhausted case, "
305 + "try with another externalIP if possible");
306 NEXT_EXTIP_FLAG = true;
309 int extPort = rpcResult.getResult().getIdValue().intValue();
310 // Write to ip-port-map before returning
311 IpPortExternalBuilder ipExt = new IpPortExternalBuilder();
312 IpPortExternal ipPortExt = ipExt.setIpAddress(extIp).setPortNum(extPort).build();
313 IpPortMap ipm = new IpPortMapBuilder().setKey(new IpPortMapKey(internalIpPort))
314 .setIpPortInternal(internalIpPort).setIpPortExternal(ipPortExt).build();
315 LOG.debug("getExternalAddressMapping : writing into ip-port-map with "
316 + "externalIP {} and port {}",
317 ipPortExt.getIpAddress(), ipPortExt.getPortNum());
319 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
320 getIpPortMapIdentifier(segmentId, internalIpPort, protocol), ipm);
321 } catch (UncheckedExecutionException uee) {
322 LOG.error("getExternalAddressMapping : Failed to write into ip-port-map with exception",
326 // Write to snat-internal-ip-port-info
327 String internalIpAddress = sourceAddress.getIpAddress();
328 int ipPort = sourceAddress.getPortNumber();
329 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
330 List<Integer> portList = new ArrayList<>(
331 NatUtil.getInternalIpPortListInfo(dataBroker, segmentId, internalIpAddress,
333 portList.add(ipPort);
335 IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
336 IntIpProtoType intIpProtocolType =
337 builder.setKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
339 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
340 NatUtil.buildSnatIntIpPortIdentifier(segmentId, internalIpAddress, protocolType),
342 } catch (Exception ex) {
343 LOG.error("getExternalAddressMapping : Failed to write into snat-internal-ip-port-info "
344 + "with exception", ex);
347 SessionAddress externalIpPort = new SessionAddress(extIp, extPort);
348 LOG.debug("getExternalAddressMapping : successfully returning externalIP {} "
349 + "and port {}", externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
350 return externalIpPort;
351 } catch (InterruptedException | ExecutionException e) {
352 LOG.error("getExternalAddressMapping : Exception caught", e);
356 } // end of else ipmap present
357 } // end of else check ipmap
358 LOG.error("getExternalAddressMapping : Unable to handle external IP address and port mapping with segmentId {},"
359 + "internalIp {} and internalPort {}", segmentId, sourceAddress.getIpAddress(),
360 sourceAddress.getPortNumber());
365 * Release the existing mapping of internal ip/port to external ip/port pair
366 * if no mapping exist for given internal ip/port, it returns false.
368 * @param segmentId - Router ID
369 * @param address - Session Address
370 * @param protocol - TCP/UDP
371 * @return true if mapping exist and the mapping is removed successfully
373 // TODO Clean up the exception handling
374 @SuppressWarnings("checkstyle:IllegalCatch")
375 public boolean releaseAddressMapping(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
376 LOG.debug("releaseAddressMapping : called with segmentId {}, internalIP {}, port {}",
377 segmentId, address.getIpAddress(), address.getPortNumber());
378 // delete entry from IpPort Map and IP Map if exists
379 String internalIpPort = address.getIpAddress() + ":" + address.getPortNumber();
380 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
381 if (existingIpPort != null) {
382 // delete the entry from IpPortMap DS
384 removeFromIpPortMapDS(segmentId, internalIpPort, protocol);
385 } catch (Exception e) {
386 LOG.error("releaseAddressMapping : failed, Removal of ipportmap {} for "
387 + "router {} failed", internalIpPort, segmentId, e);
391 LOG.error("releaseAddressMapping : failed, segmentId {} and internalIpPort {} "
392 + "not found in IpPortMap DS", segmentId, internalIpPort);
395 String existingIp = checkIpMap(segmentId, address.getIpAddress());
396 if (existingIp != null) {
397 // delete the entry from IpMap DS
399 removeFromIpMapDS(segmentId, address.getIpAddress());
400 } catch (Exception e) {
401 LOG.error("releaseAddressMapping : Removal of ipmap {} for router {} failed {}",
402 address.getIpAddress(), segmentId, e);
405 //delete the entry from snatIntIpportinfo
407 removeFromSnatIpPortDS(segmentId, address.getIpAddress());
408 } catch (Exception e) {
409 LOG.error("releaseAddressMapping : failed, Removal of snatipportmap {} for "
410 + "router {} failed", address.getIpAddress(), segmentId, e);
414 LOG.error("releaseAddressMapping : failed, segmentId {} and internalIpPort {} "
415 + "not found in IpMap DS", segmentId, internalIpPort);
418 // Finally release port from idmanager
419 removePortFromPool(internalIpPort, existingIpPort.getIpAddress());
421 LOG.debug("releaseAddressMapping : Exited successfully for segmentId {} and internalIpPort {}",
422 segmentId, internalIpPort);
426 // TODO Clean up the exception handling
427 @SuppressWarnings("checkstyle:IllegalCatch")
428 protected void releaseIpExtPortMapping(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
429 String internalIpPort = address.getIpAddress() + ":" + address.getPortNumber();
430 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
431 if (existingIpPort != null) {
432 // delete the entry from IpPortMap DS
434 removeFromIpPortMapDS(segmentId, internalIpPort, protocol);
435 // Finally release port from idmanager
436 removePortFromPool(internalIpPort, existingIpPort.getIpAddress());
437 } catch (Exception e) {
438 LOG.error("releaseIpExtPortMapping : failed, Removal of ipportmap {} for "
439 + "router {} failed", internalIpPort, segmentId, e);
442 LOG.error("releaseIpExtPortMapping : failed, segmentId {} and "
443 + "internalIpPort {} not found in IpPortMap DS", segmentId, internalIpPort);
446 //delete the entry of port for InternalIp from snatIntIpportMappingDS
448 removeSnatIntIpPortDS(segmentId, address, protocol);
449 } catch (Exception e) {
450 LOG.error("releaseSnatIpPortMapping : failed, Removal of snatipportmap {} for "
451 + "router {} failed",address.getIpAddress(), segmentId, e);
456 * Removes the internal ip to external ip mapping if present.
458 * @param segmentId - Router ID
459 * @return true if successfully removed
461 // TODO Clean up the exception handling
462 @SuppressWarnings("checkstyle:IllegalCatch")
463 public boolean removeMapping(long segmentId) {
465 removeIpMappingForRouterID(segmentId);
466 removeIpPortMappingForRouterID(segmentId);
467 removeIntIpPortMappingForRouterID(segmentId);
468 } catch (Exception e) {
469 LOG.error("removeMapping : Removal of IPMapping for router {} failed", segmentId, e);
473 //TODO : This is when router is deleted then cleanup the entries in tables, ports etc - Delete scenarios
477 protected InstanceIdentifier<IpMap> getIpMapIdentifier(long segid, String internal) {
478 return InstanceIdentifier.builder(IntextIpMap.class)
479 .child(IpMapping.class, new IpMappingKey(segid))
480 .child(IpMap.class, new IpMapKey(internal)).build();
483 protected InstanceIdentifier<ExternalIpCounter> getExternalIpsIdentifier(long segmentId, String external) {
484 return InstanceIdentifier.builder(ExternalIpsCounter.class)
485 .child(ExternalCounters.class, new ExternalCountersKey(segmentId))
486 .child(ExternalIpCounter.class, new ExternalIpCounterKey(external)).build();
490 public static List<IpMap> getIpMapList(DataBroker broker, Long routerId) {
491 InstanceIdentifier<IpMapping> id = getIpMapList(routerId);
492 return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
493 LogicalDatastoreType.OPERATIONAL, id).toJavaUtil().map(IpMapping::getIpMap).orElse(
494 Collections.emptyList());
497 protected static InstanceIdentifier<IpMapping> getIpMapList(long routerId) {
498 return InstanceIdentifier.builder(
499 IntextIpMap.class).child(IpMapping.class, new IpMappingKey(routerId)).build();
502 protected InstanceIdentifier<IpPortMap> getIpPortMapIdentifier(long segid, String internal,
503 NAPTEntryEvent.Protocol protocol) {
504 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
505 return InstanceIdentifier.builder(IntextIpPortMap.class)
506 .child(IpPortMapping.class, new IpPortMappingKey(segid))
507 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
508 .child(IpPortMap.class, new IpPortMapKey(internal)).build();
511 private SessionAddress checkIpPortMap(long segmentId, String internalIpPort,
512 NAPTEntryEvent.Protocol protocol) {
513 LOG.debug("checkIpPortMap : called with segmentId {} and internalIpPort {}",
514 segmentId, internalIpPort);
515 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
516 // check if ip-port-map node is there
517 InstanceIdentifierBuilder<IpPortMap> idBuilder =
518 InstanceIdentifier.builder(IntextIpPortMap.class)
519 .child(IpPortMapping.class, new IpPortMappingKey(segmentId))
520 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
521 .child(IpPortMap.class, new IpPortMapKey(internalIpPort));
522 InstanceIdentifier<IpPortMap> id = idBuilder.build();
523 Optional<IpPortMap> ipPortMapType =
524 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
525 if (ipPortMapType.isPresent()) {
526 LOG.debug("checkIpPortMap : {}", ipPortMapType.get());
527 SessionAddress externalIpPort = new SessionAddress(ipPortMapType.get().getIpPortExternal().getIpAddress(),
528 ipPortMapType.get().getIpPortExternal().getPortNum());
529 LOG.debug("checkIpPortMap : returning successfully externalIP {} and port {}",
530 externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
531 return externalIpPort;
533 // return null if not found
534 LOG.warn("checkIpPortMap : no-entry in checkIpPortMap, returning NULL [should be OK] for "
535 + "segmentId {} and internalIPPort {}", segmentId, internalIpPort);
539 protected String checkIpMap(long segmentId, String internalIp) {
540 LOG.debug("checkIpMap : called with segmentId {} and internalIp {}", segmentId, internalIp);
542 // check if ip-map node is there
543 InstanceIdentifierBuilder<IpMapping> idBuilder =
544 InstanceIdentifier.builder(IntextIpMap.class).child(IpMapping.class, new IpMappingKey(segmentId));
545 InstanceIdentifier<IpMapping> id = idBuilder.build();
546 Optional<IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
547 if (ipMapping.isPresent()) {
548 List<IpMap> ipMaps = ipMapping.get().getIpMap();
549 for (IpMap ipMap : ipMaps) {
550 if (ipMap.getInternalIp().equals(internalIp)) {
551 LOG.debug("checkIpMap : IpMap : {}", ipMap);
552 externalIp = ipMap.getExternalIp();
553 LOG.debug("checkIpMap : successfully returning externalIp {}", externalIp);
555 } else if (ipMap.getInternalIp().contains("/")) { // subnet case
556 SubnetUtils subnetUtils = new SubnetUtils(ipMap.getInternalIp());
557 SubnetInfo subnetInfo = subnetUtils.getInfo();
558 if (subnetInfo.isInRange(internalIp)) {
559 LOG.debug("checkIpMap : internalIp {} found to be IpMap of internalIpSubnet {}",
560 internalIp, ipMap.getInternalIp());
561 externalIp = ipMap.getExternalIp();
562 LOG.debug("checkIpMap : checkIpMap successfully returning externalIp {}", externalIp);
568 // return null if not found
569 LOG.error("checkIpMap : failed, returning NULL for segmentId {} and internalIp {}",
570 segmentId, internalIp);
574 // TODO Clean up the exception handling
575 @SuppressWarnings("checkstyle:IllegalCatch")
576 protected void removeSnatIntIpPortDS(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
577 LOG.trace("removeSnatIntIpPortDS : method called for IntIpport {} of router {} ",
579 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
580 List<Integer> portList =
581 NatUtil.getInternalIpPortListInfo(dataBroker, segmentId, address.getIpAddress(), protocolType);
582 if (portList.isEmpty() || !portList.contains(address.getPortNumber())) {
583 LOG.error("removeSnatIntIpPortDS : Internal IP {} for port {} entry not found in SnatIntIpPort DS",
584 address.getIpAddress(), address.getPortNumber());
587 LOG.trace("removeSnatIntIpPortDS : PortList {} retrieved for InternalIp {} of router {}",
588 portList, address.getIpAddress(), segmentId);
589 Integer port = address.getPortNumber();
590 portList.remove(port);
592 IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
593 IntIpProtoType intIpProtocolType =
594 builder.setKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
596 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
597 NatUtil.buildSnatIntIpPortIdentifier(segmentId, address.getIpAddress(), protocolType),
599 } catch (Exception ex) {
600 LOG.error("removeSnatIntIpPortDS : Failed to write into snat-internal-ip-port-info with exception",ex);
602 LOG.debug("removeSnatIntIpPortDS : Removing SnatIp {} Port {} of router {} from SNATIntIpport datastore : {}",
603 address.getIpAddress(), address.getPortNumber(), segmentId);
606 protected void removeFromSnatIpPortDS(long segmentId, String internalIp) {
607 InstanceIdentifier<IpPort> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class)
608 .child(IntipPortMap.class, new IntipPortMapKey(segmentId))
609 .child(IpPort.class, new IpPortKey(internalIp)).build();
610 // remove from SnatIpPortDS
611 LOG.debug("removeFromSnatIpPortDS : Removing SnatIpPort from datastore : {}", intIp);
612 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
615 protected void removeFromIpPortMapDS(long segmentId, String internalIpPort, NAPTEntryEvent.Protocol protocol) {
616 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
617 removeFromIpPortMapDS(segmentId, internalIpPort, protocolType);
620 protected void removeFromIpPortMapDS(long segmentId, String internalIpPort, ProtocolTypes protocolType) {
621 InstanceIdentifierBuilder<IpPortMap> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
622 .child(IpPortMapping.class, new IpPortMappingKey(segmentId))
623 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
624 .child(IpPortMap.class, new IpPortMapKey(internalIpPort));
625 InstanceIdentifier<IpPortMap> id = idBuilder.build();
626 // remove from ipportmap DS
627 LOG.debug("removeFromIpPortMapDS : Removing ipportmap from datastore : {}", id);
628 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
631 protected void removeFromIpMapDS(long segmentId, String internalIp) {
632 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
633 .child(IpMapping.class, new IpMappingKey(segmentId))
634 .child(IpMap.class, new IpMapKey(internalIp));
635 InstanceIdentifier<IpMap> id = idBuilder.build();
636 // Get externalIp and decrement the counter
637 String externalIp = null;
638 Optional<IpMap> ipMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
639 if (ipMap.isPresent()) {
640 externalIp = ipMap.get().getExternalIp();
641 LOG.debug("removeFromIpMapDS : externalIP is {}", externalIp);
643 LOG.warn("removeFromIpMapDS : ipMap not present for the internal IP {}", internalIp);
646 if (externalIp != null) {
647 updateCounter(segmentId, externalIp, false);
648 // remove from ipmap DS
649 LOG.debug("removeFromIpMapDS : Removing ipmap from datastore");
650 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
652 LOG.warn("removeFromIpMapDS : externalIp not present for the internal IP {}", internalIp);
656 protected void removeIntExtIpMapDS(long segmentId, String internalIp) {
657 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
658 .child(IpMapping.class, new IpMappingKey(segmentId))
659 .child(IpMap.class, new IpMapKey(internalIp));
660 InstanceIdentifier<IpMap> id = idBuilder.build();
662 LOG.debug("removeIntExtIpMapDS : Removing ipmap from datastore");
663 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
666 protected String getExternalIpAllocatedForSubnet(long segmentId, String internalIp) {
667 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
668 .child(IpMapping.class, new IpMappingKey(segmentId))
669 .child(IpMap.class, new IpMapKey(internalIp));
670 InstanceIdentifier<IpMap> id = idBuilder.build();
672 Optional<IpMap> ipMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
673 if (ipMap.isPresent()) {
674 return ipMap.get().getExternalIp();
679 private void removeIpMappingForRouterID(long segmentId) {
680 InstanceIdentifierBuilder<IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
681 .child(IpMapping.class, new IpMappingKey(segmentId));
682 InstanceIdentifier<IpMapping> id = idBuilder.build();
683 // Get all externalIps and decrement their counters before deleting the ipmap
684 String externalIp = null;
685 Optional<IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
686 if (ipMapping.isPresent()) {
687 List<IpMap> ipMaps = ipMapping.get().getIpMap();
688 for (IpMap ipMap : ipMaps) {
689 externalIp = ipMap.getExternalIp();
690 LOG.debug("removeIpMappingForRouterID : externalIP is {}", externalIp);
691 if (externalIp != null) {
692 updateCounter(segmentId, externalIp, false);
695 // remove from ipmap DS
696 LOG.debug("removeIpMappingForRouterID : Removing Ipmap for router {} from datastore", segmentId);
697 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
701 void removeIpPortMappingForRouterID(long segmentId) {
702 InstanceIdentifier<IpPortMapping> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
703 .child(IpPortMapping.class, new IpPortMappingKey(segmentId)).build();
704 Optional<IpPortMapping> ipPortMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
706 if (ipPortMapping.isPresent()) {
707 // remove from IntExtIpPortmap DS
708 LOG.debug("removeIpPortMappingForRouterID : Removing IntExtIpPort map for router {} from datastore",
710 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, idBuilder);
714 void removeIntIpPortMappingForRouterID(long segmentId) {
715 InstanceIdentifier<IntipPortMap> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class)
716 .child(IntipPortMap.class, new IntipPortMapKey(segmentId)).build();
717 Optional<IntipPortMap> intIpPortMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
718 if (intIpPortMap.isPresent()) {
719 // remove from SnatIntIpPortmap DS
720 LOG.debug("removeIntIpPortMappingForRouterID : Removing SnatIntIpPort from datastore : {}", intIp);
721 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
725 void removePortFromPool(String internalIpPort, String externalIp) {
726 LOG.debug("removePortFromPool : method called");
727 ReleaseIdInput idInput = new ReleaseIdInputBuilder()
728 .setPoolName(externalIp)
729 .setIdKey(internalIpPort).build();
731 Future<RpcResult<Void>> result = idManager.releaseId(idInput);
732 RpcResult<Void> rpcResult = result.get();
733 if (!rpcResult.isSuccessful()) {
734 LOG.error("removePortFromPool : idmanager failed to remove port from pool {}", rpcResult.getErrors());
736 LOG.debug("removePortFromPool : Removed port from pool for InternalIpPort {} with externalIp {}",
737 internalIpPort, externalIp);
738 } catch (InterruptedException | ExecutionException e) {
739 LOG.error("removePortFromPool : idmanager failed when removing entry in pool with key {} with Exception",
744 protected void initialiseExternalCounter(Routers routers, long routerId) {
745 LOG.debug("initialiseExternalCounter : Initialise External IPs counter");
746 List<ExternalIps> externalIps = routers.getExternalIps();
748 //update the new counter value for this externalIp
749 for (ExternalIps externalIp : externalIps) {
750 String[] ipSplit = externalIp.getIpAddress().split("/");
751 String extIp = ipSplit[0];
752 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
753 if (ipSplit.length == 2) {
754 extPrefix = ipSplit[1];
756 extIp = extIp + "/" + extPrefix;
757 initialiseNewExternalIpCounter(routerId, extIp);
761 protected void initialiseNewExternalIpCounter(long routerId, String externalIp) {
762 ExternalIpCounter externalIpCounterData = new ExternalIpCounterBuilder()
763 .setKey(new ExternalIpCounterKey(externalIp)).setExternalIp(externalIp).setCounter((short) 0).build();
764 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
765 getExternalIpsIdentifier(routerId, externalIp), externalIpCounterData);
768 protected void removeExternalCounter(long routerId) {
769 // Remove from external-counters model
770 InstanceIdentifier<ExternalCounters> id = InstanceIdentifier.builder(ExternalIpsCounter.class)
771 .child(ExternalCounters.class, new ExternalCountersKey(routerId)).build();
772 LOG.debug("removeExternalCounter : Removing ExternalCounterd from datastore");
773 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
776 protected void removeExternalIpCounter(long routerId, String externalIp) {
777 // Remove from external-counters model
778 InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class)
779 .child(ExternalCounters.class, new ExternalCountersKey(routerId))
780 .child(ExternalIpCounter.class, new ExternalIpCounterKey(externalIp)).build();
781 LOG.debug("removeExternalIpCounter : Removing ExternalIpsCounter from datastore");
782 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);