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);
84 private static final long LOW_PORT = 49152L;
85 private static final long HIGH_PORT = 65535L;
87 private final DataBroker dataBroker;
88 private final IdManagerService idManager;
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 boolean extSubnetFlag = false;
267 if (!externalIp.contains(subnetPrefix)) {
268 extSubnetFlag = true;
269 externalIpSubnet = new SubnetUtils(externalIp);
270 allIps = Arrays.asList(externalIpSubnet.getInfo().getAllAddresses());
271 LOG.debug("getExternalAddressMapping : total count of externalIps available {}",
272 externalIpSubnet.getInfo().getAddressCount());
274 LOG.debug("getExternalAddressMapping : getExternalAddress single ip case");
275 if (externalIp.contains(subnetPrefix)) {
276 //remove /32 what we got from checkIpMap
277 externalIp = externalIp.substring(0, externalIp.indexOf(subnetPrefix));
279 allIps.add(externalIp);
282 boolean nextExtIpFlag = false;
283 for (String extIp : allIps) {
284 LOG.info("getExternalAddressMapping : Looping externalIPs with externalIP now as {}", extIp);
286 createNaptPortPool(extIp);
287 LOG.debug("getExternalAddressMapping : Created Pool for next Ext IP {}", extIp);
289 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
290 .setPoolName(extIp).setIdKey(internalIpPort)
293 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
294 RpcResult<AllocateIdOutput> rpcResult;
295 if (result != null && result.get().isSuccessful()) {
296 LOG.debug("getExternalAddressMapping : Got id from idManager");
297 rpcResult = result.get();
299 LOG.error("getExternalAddressMapping : getExternalAddressMapping, idManager could not "
300 + "allocate id retry if subnet");
301 if (!extSubnetFlag) {
302 LOG.error("getExternalAddressMapping : getExternalAddressMapping returning null "
303 + "for single IP case, may be ports exhausted");
306 LOG.debug("getExternalAddressMapping : Could be ports exhausted case, "
307 + "try with another externalIP if possible");
308 nextExtIpFlag = true;
311 int extPort = rpcResult.getResult().getIdValue().intValue();
312 // Write to ip-port-map before returning
313 IpPortExternalBuilder ipExt = new IpPortExternalBuilder();
314 IpPortExternal ipPortExt = ipExt.setIpAddress(extIp).setPortNum(extPort).build();
315 IpPortMap ipm = new IpPortMapBuilder().setKey(new IpPortMapKey(internalIpPort))
316 .setIpPortInternal(internalIpPort).setIpPortExternal(ipPortExt).build();
317 LOG.debug("getExternalAddressMapping : writing into ip-port-map with "
318 + "externalIP {} and port {}",
319 ipPortExt.getIpAddress(), ipPortExt.getPortNum());
321 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
322 getIpPortMapIdentifier(segmentId, internalIpPort, protocol), ipm);
323 } catch (UncheckedExecutionException uee) {
324 LOG.error("getExternalAddressMapping : Failed to write into ip-port-map with exception",
328 // Write to snat-internal-ip-port-info
329 String internalIpAddress = sourceAddress.getIpAddress();
330 int ipPort = sourceAddress.getPortNumber();
331 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
332 List<Integer> portList = new ArrayList<>(
333 NatUtil.getInternalIpPortListInfo(dataBroker, segmentId, internalIpAddress,
335 portList.add(ipPort);
337 IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
338 IntIpProtoType intIpProtocolType =
339 builder.setKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
341 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
342 NatUtil.buildSnatIntIpPortIdentifier(segmentId, internalIpAddress, protocolType),
344 } catch (Exception ex) {
345 LOG.error("getExternalAddressMapping : Failed to write into snat-internal-ip-port-info "
346 + "with exception", ex);
349 SessionAddress externalIpPort = new SessionAddress(extIp, extPort);
350 LOG.debug("getExternalAddressMapping : successfully returning externalIP {} "
351 + "and port {}", externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
352 return externalIpPort;
353 } catch (InterruptedException | ExecutionException e) {
354 LOG.error("getExternalAddressMapping : Exception caught", e);
358 } // end of else ipmap present
359 } // end of else check ipmap
360 LOG.error("getExternalAddressMapping : Unable to handle external IP address and port mapping with segmentId {},"
361 + "internalIp {} and internalPort {}", segmentId, sourceAddress.getIpAddress(),
362 sourceAddress.getPortNumber());
367 * Release the existing mapping of internal ip/port to external ip/port pair
368 * if no mapping exist for given internal ip/port, it returns false.
370 * @param segmentId - Router ID
371 * @param address - Session Address
372 * @param protocol - TCP/UDP
373 * @return true if mapping exist and the mapping is removed successfully
375 // TODO Clean up the exception handling
376 @SuppressWarnings("checkstyle:IllegalCatch")
377 public boolean releaseAddressMapping(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
378 LOG.debug("releaseAddressMapping : called with segmentId {}, internalIP {}, port {}",
379 segmentId, address.getIpAddress(), address.getPortNumber());
380 // delete entry from IpPort Map and IP Map if exists
381 String internalIpPort = address.getIpAddress() + ":" + address.getPortNumber();
382 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
383 if (existingIpPort != null) {
384 // delete the entry from IpPortMap DS
386 removeFromIpPortMapDS(segmentId, internalIpPort, protocol);
387 } catch (Exception e) {
388 LOG.error("releaseAddressMapping : failed, Removal of ipportmap {} for "
389 + "router {} failed", internalIpPort, segmentId, e);
393 LOG.error("releaseAddressMapping : failed, segmentId {} and internalIpPort {} "
394 + "not found in IpPortMap DS", segmentId, internalIpPort);
397 String existingIp = checkIpMap(segmentId, address.getIpAddress());
398 if (existingIp != null) {
399 // delete the entry from IpMap DS
401 removeFromIpMapDS(segmentId, address.getIpAddress());
402 } catch (Exception e) {
403 LOG.error("releaseAddressMapping : Removal of ipmap {} for router {} failed",
404 address.getIpAddress(), segmentId, e);
407 //delete the entry from snatIntIpportinfo
409 removeFromSnatIpPortDS(segmentId, address.getIpAddress());
410 } catch (Exception e) {
411 LOG.error("releaseAddressMapping : failed, Removal of snatipportmap {} for "
412 + "router {} failed", address.getIpAddress(), segmentId, e);
416 LOG.error("releaseAddressMapping : failed, segmentId {} and internalIpPort {} "
417 + "not found in IpMap DS", segmentId, internalIpPort);
420 // Finally release port from idmanager
421 removePortFromPool(internalIpPort, existingIpPort.getIpAddress());
423 LOG.debug("releaseAddressMapping : Exited successfully for segmentId {} and internalIpPort {}",
424 segmentId, internalIpPort);
428 // TODO Clean up the exception handling
429 @SuppressWarnings("checkstyle:IllegalCatch")
430 protected void releaseIpExtPortMapping(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
431 String internalIpPort = address.getIpAddress() + ":" + address.getPortNumber();
432 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
433 if (existingIpPort != null) {
434 // delete the entry from IpPortMap DS
436 removeFromIpPortMapDS(segmentId, internalIpPort, protocol);
437 // Finally release port from idmanager
438 removePortFromPool(internalIpPort, existingIpPort.getIpAddress());
439 } catch (Exception e) {
440 LOG.error("releaseIpExtPortMapping : failed, Removal of ipportmap {} for "
441 + "router {} failed", internalIpPort, segmentId, e);
444 LOG.error("releaseIpExtPortMapping : failed, segmentId {} and "
445 + "internalIpPort {} not found in IpPortMap DS", segmentId, internalIpPort);
448 //delete the entry of port for InternalIp from snatIntIpportMappingDS
450 removeSnatIntIpPortDS(segmentId, address, protocol);
451 } catch (Exception e) {
452 LOG.error("releaseSnatIpPortMapping : failed, Removal of snatipportmap {} for "
453 + "router {} failed",address.getIpAddress(), segmentId, e);
458 * Removes the internal ip to external ip mapping if present.
460 * @param segmentId - Router ID
461 * @return true if successfully removed
463 // TODO Clean up the exception handling
464 @SuppressWarnings("checkstyle:IllegalCatch")
465 public boolean removeMapping(long segmentId) {
467 removeIpMappingForRouterID(segmentId);
468 removeIpPortMappingForRouterID(segmentId);
469 removeIntIpPortMappingForRouterID(segmentId);
470 } catch (Exception e) {
471 LOG.error("removeMapping : Removal of IPMapping for router {} failed", segmentId, e);
475 //TODO : This is when router is deleted then cleanup the entries in tables, ports etc - Delete scenarios
479 protected InstanceIdentifier<IpMap> getIpMapIdentifier(long segid, String internal) {
480 return InstanceIdentifier.builder(IntextIpMap.class)
481 .child(IpMapping.class, new IpMappingKey(segid))
482 .child(IpMap.class, new IpMapKey(internal)).build();
485 protected InstanceIdentifier<ExternalIpCounter> getExternalIpsIdentifier(long segmentId, String external) {
486 return InstanceIdentifier.builder(ExternalIpsCounter.class)
487 .child(ExternalCounters.class, new ExternalCountersKey(segmentId))
488 .child(ExternalIpCounter.class, new ExternalIpCounterKey(external)).build();
492 public static List<IpMap> getIpMapList(DataBroker broker, Long routerId) {
493 InstanceIdentifier<IpMapping> id = getIpMapList(routerId);
494 return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
495 LogicalDatastoreType.OPERATIONAL, id).toJavaUtil().map(IpMapping::getIpMap).orElse(
496 Collections.emptyList());
499 protected static InstanceIdentifier<IpMapping> getIpMapList(long routerId) {
500 return InstanceIdentifier.builder(
501 IntextIpMap.class).child(IpMapping.class, new IpMappingKey(routerId)).build();
504 protected InstanceIdentifier<IpPortMap> getIpPortMapIdentifier(long segid, String internal,
505 NAPTEntryEvent.Protocol protocol) {
506 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
507 return InstanceIdentifier.builder(IntextIpPortMap.class)
508 .child(IpPortMapping.class, new IpPortMappingKey(segid))
509 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
510 .child(IpPortMap.class, new IpPortMapKey(internal)).build();
513 private SessionAddress checkIpPortMap(long segmentId, String internalIpPort,
514 NAPTEntryEvent.Protocol protocol) {
515 LOG.debug("checkIpPortMap : called with segmentId {} and internalIpPort {}",
516 segmentId, internalIpPort);
517 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
518 // check if ip-port-map node is there
519 InstanceIdentifierBuilder<IpPortMap> idBuilder =
520 InstanceIdentifier.builder(IntextIpPortMap.class)
521 .child(IpPortMapping.class, new IpPortMappingKey(segmentId))
522 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
523 .child(IpPortMap.class, new IpPortMapKey(internalIpPort));
524 InstanceIdentifier<IpPortMap> id = idBuilder.build();
525 Optional<IpPortMap> ipPortMapType =
526 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
527 if (ipPortMapType.isPresent()) {
528 LOG.debug("checkIpPortMap : {}", ipPortMapType.get());
529 SessionAddress externalIpPort = new SessionAddress(ipPortMapType.get().getIpPortExternal().getIpAddress(),
530 ipPortMapType.get().getIpPortExternal().getPortNum());
531 LOG.debug("checkIpPortMap : returning successfully externalIP {} and port {}",
532 externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
533 return externalIpPort;
535 // return null if not found
536 LOG.warn("checkIpPortMap : no-entry in checkIpPortMap, returning NULL [should be OK] for "
537 + "segmentId {} and internalIPPort {}", segmentId, internalIpPort);
541 protected String checkIpMap(long segmentId, String internalIp) {
542 LOG.debug("checkIpMap : called with segmentId {} and internalIp {}", segmentId, internalIp);
544 // check if ip-map node is there
545 InstanceIdentifierBuilder<IpMapping> idBuilder =
546 InstanceIdentifier.builder(IntextIpMap.class).child(IpMapping.class, new IpMappingKey(segmentId));
547 InstanceIdentifier<IpMapping> id = idBuilder.build();
548 Optional<IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
549 if (ipMapping.isPresent()) {
550 List<IpMap> ipMaps = ipMapping.get().getIpMap();
551 for (IpMap ipMap : ipMaps) {
552 if (ipMap.getInternalIp().equals(internalIp)) {
553 LOG.debug("checkIpMap : IpMap : {}", ipMap);
554 externalIp = ipMap.getExternalIp();
555 LOG.debug("checkIpMap : successfully returning externalIp {}", externalIp);
557 } else if (ipMap.getInternalIp().contains("/")) { // subnet case
558 SubnetUtils subnetUtils = new SubnetUtils(ipMap.getInternalIp());
559 SubnetInfo subnetInfo = subnetUtils.getInfo();
560 if (subnetInfo.isInRange(internalIp)) {
561 LOG.debug("checkIpMap : internalIp {} found to be IpMap of internalIpSubnet {}",
562 internalIp, ipMap.getInternalIp());
563 externalIp = ipMap.getExternalIp();
564 LOG.debug("checkIpMap : checkIpMap successfully returning externalIp {}", externalIp);
570 // return null if not found
571 LOG.error("checkIpMap : failed, returning NULL for segmentId {} and internalIp {}",
572 segmentId, internalIp);
576 // TODO Clean up the exception handling
577 @SuppressWarnings("checkstyle:IllegalCatch")
578 protected void removeSnatIntIpPortDS(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
579 LOG.trace("removeSnatIntIpPortDS : method called for IntIpport {} of router {} ",
581 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
582 List<Integer> portList =
583 NatUtil.getInternalIpPortListInfo(dataBroker, segmentId, address.getIpAddress(), protocolType);
584 if (portList.isEmpty() || !portList.contains(address.getPortNumber())) {
585 LOG.error("removeSnatIntIpPortDS : Internal IP {} for port {} entry not found in SnatIntIpPort DS",
586 address.getIpAddress(), address.getPortNumber());
589 LOG.trace("removeSnatIntIpPortDS : PortList {} retrieved for InternalIp {} of router {}",
590 portList, address.getIpAddress(), segmentId);
591 Integer port = address.getPortNumber();
592 portList.remove(port);
594 IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
595 IntIpProtoType intIpProtocolType =
596 builder.setKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
598 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
599 NatUtil.buildSnatIntIpPortIdentifier(segmentId, address.getIpAddress(), protocolType),
601 } catch (Exception ex) {
602 LOG.error("removeSnatIntIpPortDS : Failed to write into snat-internal-ip-port-info with exception", ex);
604 LOG.debug("removeSnatIntIpPortDS : Removing SnatIp {} Port {} of router {} from SNATIntIpport datastore",
605 address.getIpAddress(), address.getPortNumber(), segmentId);
608 protected void removeFromSnatIpPortDS(long segmentId, String internalIp) {
609 InstanceIdentifier<IpPort> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class)
610 .child(IntipPortMap.class, new IntipPortMapKey(segmentId))
611 .child(IpPort.class, new IpPortKey(internalIp)).build();
612 // remove from SnatIpPortDS
613 LOG.debug("removeFromSnatIpPortDS : Removing SnatIpPort from datastore : {}", intIp);
614 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
617 protected void removeFromIpPortMapDS(long segmentId, String internalIpPort, NAPTEntryEvent.Protocol protocol) {
618 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
619 removeFromIpPortMapDS(segmentId, internalIpPort, protocolType);
622 protected void removeFromIpPortMapDS(long segmentId, String internalIpPort, ProtocolTypes protocolType) {
623 InstanceIdentifierBuilder<IpPortMap> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
624 .child(IpPortMapping.class, new IpPortMappingKey(segmentId))
625 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
626 .child(IpPortMap.class, new IpPortMapKey(internalIpPort));
627 InstanceIdentifier<IpPortMap> id = idBuilder.build();
628 // remove from ipportmap DS
629 LOG.debug("removeFromIpPortMapDS : Removing ipportmap from datastore : {}", id);
630 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
633 protected void removeFromIpMapDS(long segmentId, String internalIp) {
634 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
635 .child(IpMapping.class, new IpMappingKey(segmentId))
636 .child(IpMap.class, new IpMapKey(internalIp));
637 InstanceIdentifier<IpMap> id = idBuilder.build();
638 // Get externalIp and decrement the counter
639 String externalIp = null;
640 Optional<IpMap> ipMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
641 if (ipMap.isPresent()) {
642 externalIp = ipMap.get().getExternalIp();
643 LOG.debug("removeFromIpMapDS : externalIP is {}", externalIp);
645 LOG.warn("removeFromIpMapDS : ipMap not present for the internal IP {}", internalIp);
648 if (externalIp != null) {
649 updateCounter(segmentId, externalIp, false);
650 // remove from ipmap DS
651 LOG.debug("removeFromIpMapDS : Removing ipmap from datastore");
652 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
654 LOG.warn("removeFromIpMapDS : externalIp not present for the internal IP {}", internalIp);
658 protected void removeIntExtIpMapDS(long segmentId, String internalIp) {
659 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
660 .child(IpMapping.class, new IpMappingKey(segmentId))
661 .child(IpMap.class, new IpMapKey(internalIp));
662 InstanceIdentifier<IpMap> id = idBuilder.build();
664 LOG.debug("removeIntExtIpMapDS : Removing ipmap from datastore");
665 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
668 protected String getExternalIpAllocatedForSubnet(long segmentId, String internalIp) {
669 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
670 .child(IpMapping.class, new IpMappingKey(segmentId))
671 .child(IpMap.class, new IpMapKey(internalIp));
672 InstanceIdentifier<IpMap> id = idBuilder.build();
674 Optional<IpMap> ipMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
675 if (ipMap.isPresent()) {
676 return ipMap.get().getExternalIp();
681 private void removeIpMappingForRouterID(long segmentId) {
682 InstanceIdentifierBuilder<IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
683 .child(IpMapping.class, new IpMappingKey(segmentId));
684 InstanceIdentifier<IpMapping> id = idBuilder.build();
685 // Get all externalIps and decrement their counters before deleting the ipmap
686 String externalIp = null;
687 Optional<IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
688 if (ipMapping.isPresent()) {
689 List<IpMap> ipMaps = ipMapping.get().getIpMap();
690 for (IpMap ipMap : ipMaps) {
691 externalIp = ipMap.getExternalIp();
692 LOG.debug("removeIpMappingForRouterID : externalIP is {}", externalIp);
693 if (externalIp != null) {
694 updateCounter(segmentId, externalIp, false);
697 // remove from ipmap DS
698 LOG.debug("removeIpMappingForRouterID : Removing Ipmap for router {} from datastore", segmentId);
699 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
703 void removeIpPortMappingForRouterID(long segmentId) {
704 InstanceIdentifier<IpPortMapping> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
705 .child(IpPortMapping.class, new IpPortMappingKey(segmentId)).build();
706 Optional<IpPortMapping> ipPortMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
708 if (ipPortMapping.isPresent()) {
709 // remove from IntExtIpPortmap DS
710 LOG.debug("removeIpPortMappingForRouterID : Removing IntExtIpPort map for router {} from datastore",
712 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, idBuilder);
716 void removeIntIpPortMappingForRouterID(long segmentId) {
717 InstanceIdentifier<IntipPortMap> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class)
718 .child(IntipPortMap.class, new IntipPortMapKey(segmentId)).build();
719 Optional<IntipPortMap> intIpPortMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
720 if (intIpPortMap.isPresent()) {
721 // remove from SnatIntIpPortmap DS
722 LOG.debug("removeIntIpPortMappingForRouterID : Removing SnatIntIpPort from datastore : {}", intIp);
723 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
727 void removePortFromPool(String internalIpPort, String externalIp) {
728 LOG.debug("removePortFromPool : method called");
729 ReleaseIdInput idInput = new ReleaseIdInputBuilder()
730 .setPoolName(externalIp)
731 .setIdKey(internalIpPort).build();
733 Future<RpcResult<Void>> result = idManager.releaseId(idInput);
734 RpcResult<Void> rpcResult = result.get();
735 if (!rpcResult.isSuccessful()) {
736 LOG.error("removePortFromPool : idmanager failed to remove port from pool {}", rpcResult.getErrors());
738 LOG.debug("removePortFromPool : Removed port from pool for InternalIpPort {} with externalIp {}",
739 internalIpPort, externalIp);
740 } catch (InterruptedException | ExecutionException e) {
741 LOG.error("removePortFromPool : idmanager failed when removing entry in pool with key {} with Exception",
746 protected void initialiseExternalCounter(Routers routers, long routerId) {
747 LOG.debug("initialiseExternalCounter : Initialise External IPs counter");
748 List<ExternalIps> externalIps = routers.getExternalIps();
750 //update the new counter value for this externalIp
751 for (ExternalIps externalIp : externalIps) {
752 String[] ipSplit = externalIp.getIpAddress().split("/");
753 String extIp = ipSplit[0];
754 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
755 if (ipSplit.length == 2) {
756 extPrefix = ipSplit[1];
758 extIp = extIp + "/" + extPrefix;
759 initialiseNewExternalIpCounter(routerId, extIp);
763 protected void initialiseNewExternalIpCounter(long routerId, String externalIp) {
764 ExternalIpCounter externalIpCounterData = new ExternalIpCounterBuilder()
765 .setKey(new ExternalIpCounterKey(externalIp)).setExternalIp(externalIp).setCounter((short) 0).build();
766 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
767 getExternalIpsIdentifier(routerId, externalIp), externalIpCounterData);
770 protected void removeExternalCounter(long routerId) {
771 // Remove from external-counters model
772 InstanceIdentifier<ExternalCounters> id = InstanceIdentifier.builder(ExternalIpsCounter.class)
773 .child(ExternalCounters.class, new ExternalCountersKey(routerId)).build();
774 LOG.debug("removeExternalCounter : Removing ExternalCounterd from datastore");
775 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
778 protected void removeExternalIpCounter(long routerId, String externalIp) {
779 // Remove from external-counters model
780 InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class)
781 .child(ExternalCounters.class, new ExternalCountersKey(routerId))
782 .child(ExternalIpCounter.class, new ExternalIpCounterKey(externalIp)).build();
783 LOG.debug("removeExternalIpCounter : Removing ExternalIpsCounter from datastore");
784 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);