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.CreateIdPoolOutput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInputBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolOutput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpMap;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.SnatintIpPortMap;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCountersKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounterBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounterKey;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMappingKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolTypeKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapKey;
68 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;
69 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;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMap;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMapKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPortKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeKey;
77 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
78 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
79 import org.opendaylight.yangtools.yang.common.RpcResult;
80 import org.slf4j.Logger;
81 import org.slf4j.LoggerFactory;
84 public class NaptManager {
85 private static final Logger LOG = LoggerFactory.getLogger(NaptManager.class);
87 private static final long LOW_PORT = 49152L;
88 private static final long HIGH_PORT = 65535L;
90 private final DataBroker dataBroker;
91 private final IdManagerService idManager;
94 public NaptManager(final DataBroker dataBroker, final IdManagerService idManager) {
95 this.dataBroker = dataBroker;
96 this.idManager = idManager;
99 protected void createNaptPortPool(String poolName) {
100 LOG.debug("createNaptPortPool : requested for : {}", poolName);
101 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
102 .setPoolName(poolName)
107 Future<RpcResult<CreateIdPoolOutput>> result = idManager.createIdPool(createPool);
108 if (result != null && result.get().isSuccessful()) {
109 LOG.debug("createNaptPortPool : Created PortPool :{}", poolName);
111 LOG.error("createNaptPortPool : Unable to create PortPool : {}", poolName);
113 } catch (InterruptedException | ExecutionException e) {
114 LOG.error("createNaptPortPool : Failed to create PortPool for NAPT Service", e);
118 void removeNaptPortPool(String poolName) {
119 DeleteIdPoolInput deleteIdPoolInput = new DeleteIdPoolInputBuilder().setPoolName(poolName).build();
120 LOG.debug("removeNaptPortPool : Remove Napt port pool requested for : {}", poolName);
122 Future<RpcResult<DeleteIdPoolOutput>> result = idManager.deleteIdPool(deleteIdPoolInput);
123 if (result != null && result.get().isSuccessful()) {
124 LOG.debug("removeNaptPortPool : Deleted PortPool {}", poolName);
126 LOG.error("removeNaptPortPool : Unable to delete PortPool {}", poolName);
128 } catch (InterruptedException | ExecutionException e) {
129 LOG.error("removeNaptPortPool : Failed to delete PortPool {} for NAPT Service", poolName, e);
133 // 1. napt service functions
136 * This method is used to inform this service of what external IP address to be used
137 * as mapping when requested one for the internal IP address given in the input.
139 * @param segmentId – segmentation in which the mapping to be used. Eg; routerid
140 * @param internal subnet prefix or ip address
141 * @param external subnet prefix or ip address
144 public void registerMapping(long segmentId, IPAddress internal, IPAddress external) {
145 LOG.debug("registerMapping : called with segmentid {}, internalIp {}, prefix {}, externalIp {} "
146 + "and prefix {} ", segmentId, internal.getIpAddress(),
147 internal.getPrefixLength(), external.getIpAddress(), external.getPrefixLength());
148 // Create Pool per ExternalIp and not for all IPs in the subnet.
149 // Create new Pools during getExternalAddressMapping if exhausted.
150 String externalIpPool;
152 if (external.getPrefixLength() != 0 && external.getPrefixLength() != NatConstants.DEFAULT_PREFIX) {
153 String externalSubnet = external.getIpAddress() + "/" + external.getPrefixLength();
154 LOG.debug("registerMapping : externalSubnet is : {}", externalSubnet);
155 SubnetUtils subnetUtils = new SubnetUtils(externalSubnet);
156 SubnetInfo subnetInfo = subnetUtils.getInfo();
157 externalIpPool = subnetInfo.getLowAddress();
159 externalIpPool = external.getIpAddress();
161 createNaptPortPool(externalIpPool);
163 // Store the ip to ip map in Operational DS
164 String internalIp = internal.getIpAddress();
165 if (internal.getPrefixLength() != 0) {
166 internalIp = internal.getIpAddress() + "/" + internal.getPrefixLength();
168 String externalIp = external.getIpAddress();
169 if (external.getPrefixLength() != 0) {
170 externalIp = external.getIpAddress() + "/" + external.getPrefixLength();
172 updateCounter(segmentId, externalIp, true);
173 //update the actual ip-map
174 IpMap ipm = new IpMapBuilder().withKey(new IpMapKey(internalIp)).setInternalIp(internalIp)
175 .setExternalIp(externalIp).build();
176 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
177 getIpMapIdentifier(segmentId, internalIp), ipm);
178 LOG.debug("registerMapping : registerMapping exit after updating DS with internalIP {}, externalIP {}",
179 internalIp, externalIp);
182 public void updateCounter(long segmentId, String externalIp, boolean isAdd) {
184 InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class)
185 .child(ExternalCounters.class, new ExternalCountersKey(segmentId))
186 .child(ExternalIpCounter.class, new ExternalIpCounterKey(externalIp)).build();
187 Optional<ExternalIpCounter> externalIpCounter =
188 MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
189 if (externalIpCounter.isPresent()) {
190 counter = externalIpCounter.get().getCounter();
193 LOG.debug("updateCounter : externalIp and counter after increment are {} and {}", externalIp, counter);
198 LOG.debug("updateCounter : externalIp and counter after decrement are {} and {}", externalIp, counter);
205 //update the new counter value for this externalIp
206 ExternalIpCounter externalIpCounterData = new ExternalIpCounterBuilder()
207 .withKey(new ExternalIpCounterKey(externalIp)).setExternalIp(externalIp).setCounter(counter).build();
208 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
209 getExternalIpsIdentifier(segmentId, externalIp), externalIpCounterData);
213 * method to get external ip/port mapping when provided with internal ip/port pair
214 * If already a mapping exist for the given input, then the existing mapping is returned
215 * instead of overwriting with new ip/port pair.
217 * @param segmentId - Router ID
218 * @param sourceAddress - internal ip address/port pair
219 * @param protocol - TCP/UDP
220 * @return external ip address/port
222 // TODO Clean up the exception handling
223 @SuppressWarnings("checkstyle:IllegalCatch")
224 public SessionAddress getExternalAddressMapping(long segmentId, SessionAddress sourceAddress,
225 NAPTEntryEvent.Protocol protocol) {
226 LOG.debug("getExternalAddressMapping : called with segmentId {}, internalIp {} and port {}",
227 segmentId, sourceAddress.getIpAddress(), sourceAddress.getPortNumber());
229 1. Get Internal IP, Port in IP:Port format
230 2. Inside DB with routerId get the list of entries and check if it matches with existing IP:Port
231 3. If True return SessionAddress of ExternalIp and Port
232 4. Else check ip Map and Form the ExternalIp and Port and update DB and then return ExternalIp and Port
235 //SessionAddress externalIpPort = new SessionAddress();
236 String internalIpPort = sourceAddress.getIpAddress() + ":" + sourceAddress.getPortNumber();
238 // First check existing Port Map.
239 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
240 if (existingIpPort != null) {
241 // populate externalIpPort from IpPortMap and return
242 LOG.debug("getExternalAddressMapping : successfully returning existingIpPort as {} and {}",
243 existingIpPort.getIpAddress(), existingIpPort.getPortNumber());
244 return existingIpPort;
246 // Now check in ip-map
247 String externalIp = checkIpMap(segmentId, sourceAddress.getIpAddress());
248 if (externalIp == null) {
249 LOG.error("getExternalAddressMapping : Unexpected error, internal to external "
250 + "ip map does not exist");
253 /* Logic assuming internalIp is always ip and not subnet
254 * case 1: externalIp is ip
255 * a) goto externalIp pool and getPort and return
256 * b) else return error
257 * case 2: externalIp is subnet
258 * a) Take first externalIp and goto that Pool and getPort
260 * else Take second externalIp and create that Pool and getPort
263 * Continue same with third externalIp till we exhaust subnet
264 * b) Nothing worked return error
266 SubnetUtils externalIpSubnet;
267 List<String> allIps = new ArrayList<>();
268 String subnetPrefix = "/" + String.valueOf(NatConstants.DEFAULT_PREFIX);
269 boolean extSubnetFlag = false;
270 if (!externalIp.contains(subnetPrefix)) {
271 extSubnetFlag = true;
272 externalIpSubnet = new SubnetUtils(externalIp);
273 allIps = Arrays.asList(externalIpSubnet.getInfo().getAllAddresses());
274 LOG.debug("getExternalAddressMapping : total count of externalIps available {}",
275 externalIpSubnet.getInfo().getAddressCount());
277 LOG.debug("getExternalAddressMapping : getExternalAddress single ip case");
278 if (externalIp.contains(subnetPrefix)) {
279 //remove /32 what we got from checkIpMap
280 externalIp = externalIp.substring(0, externalIp.indexOf(subnetPrefix));
282 allIps.add(externalIp);
285 boolean nextExtIpFlag = false;
286 for (String extIp : allIps) {
287 LOG.info("getExternalAddressMapping : Looping externalIPs with externalIP now as {}", extIp);
289 createNaptPortPool(extIp);
290 LOG.debug("getExternalAddressMapping : Created Pool for next Ext IP {}", extIp);
292 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
293 .setPoolName(extIp).setIdKey(internalIpPort)
296 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
297 RpcResult<AllocateIdOutput> rpcResult;
298 if (result != null && result.get().isSuccessful()) {
299 LOG.debug("getExternalAddressMapping : Got id from idManager");
300 rpcResult = result.get();
302 LOG.error("getExternalAddressMapping : getExternalAddressMapping, idManager could not "
303 + "allocate id retry if subnet");
304 if (!extSubnetFlag) {
305 LOG.error("getExternalAddressMapping : getExternalAddressMapping returning null "
306 + "for single IP case, may be ports exhausted");
309 LOG.debug("getExternalAddressMapping : Could be ports exhausted case, "
310 + "try with another externalIP if possible");
311 nextExtIpFlag = true;
314 int extPort = rpcResult.getResult().getIdValue().intValue();
315 // Write to ip-port-map before returning
316 IpPortExternalBuilder ipExt = new IpPortExternalBuilder();
317 IpPortExternal ipPortExt = ipExt.setIpAddress(extIp).setPortNum(extPort).build();
318 IpPortMap ipm = new IpPortMapBuilder().withKey(new IpPortMapKey(internalIpPort))
319 .setIpPortInternal(internalIpPort).setIpPortExternal(ipPortExt).build();
320 LOG.debug("getExternalAddressMapping : writing into ip-port-map with "
321 + "externalIP {} and port {}",
322 ipPortExt.getIpAddress(), ipPortExt.getPortNum());
324 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
325 getIpPortMapIdentifier(segmentId, internalIpPort, protocol), ipm);
326 } catch (UncheckedExecutionException uee) {
327 LOG.error("getExternalAddressMapping : Failed to write into ip-port-map with exception",
331 // Write to snat-internal-ip-port-info
332 String internalIpAddress = sourceAddress.getIpAddress();
333 int ipPort = sourceAddress.getPortNumber();
334 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
335 List<Integer> portList = new ArrayList<>(
336 NatUtil.getInternalIpPortListInfo(dataBroker, segmentId, internalIpAddress,
338 portList.add(ipPort);
340 IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
341 IntIpProtoType intIpProtocolType =
342 builder.withKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
344 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
345 NatUtil.buildSnatIntIpPortIdentifier(segmentId, internalIpAddress, protocolType),
347 } catch (Exception ex) {
348 LOG.error("getExternalAddressMapping : Failed to write into snat-internal-ip-port-info "
349 + "with exception", ex);
352 SessionAddress externalIpPort = new SessionAddress(extIp, extPort);
353 LOG.debug("getExternalAddressMapping : successfully returning externalIP {} "
354 + "and port {}", externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
355 return externalIpPort;
356 } catch (InterruptedException | ExecutionException e) {
357 LOG.error("getExternalAddressMapping : Exception caught", e);
361 } // end of else ipmap present
362 } // end of else check ipmap
363 LOG.error("getExternalAddressMapping : Unable to handle external IP address and port mapping with segmentId {},"
364 + "internalIp {} and internalPort {}", segmentId, sourceAddress.getIpAddress(),
365 sourceAddress.getPortNumber());
370 * Release the existing mapping of internal ip/port to external ip/port pair
371 * if no mapping exist for given internal ip/port, it returns false.
373 * @param segmentId - Router ID
374 * @param address - Session Address
375 * @param protocol - TCP/UDP
376 * @return true if mapping exist and the mapping is removed successfully
378 // TODO Clean up the exception handling
379 @SuppressWarnings("checkstyle:IllegalCatch")
380 public boolean releaseAddressMapping(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
381 LOG.debug("releaseAddressMapping : called with segmentId {}, internalIP {}, port {}",
382 segmentId, address.getIpAddress(), address.getPortNumber());
383 // delete entry from IpPort Map and IP Map if exists
384 String internalIpPort = address.getIpAddress() + ":" + address.getPortNumber();
385 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
386 if (existingIpPort != null) {
387 // delete the entry from IpPortMap DS
389 removeFromIpPortMapDS(segmentId, internalIpPort, protocol);
390 } catch (Exception e) {
391 LOG.error("releaseAddressMapping : failed, Removal of ipportmap {} for "
392 + "router {} failed", internalIpPort, segmentId, e);
396 LOG.error("releaseAddressMapping : failed, segmentId {} and internalIpPort {} "
397 + "not found in IpPortMap DS", segmentId, internalIpPort);
400 String existingIp = checkIpMap(segmentId, address.getIpAddress());
401 if (existingIp != null) {
402 // delete the entry from IpMap DS
404 removeFromIpMapDS(segmentId, address.getIpAddress());
405 } catch (Exception e) {
406 LOG.error("releaseAddressMapping : Removal of ipmap {} for router {} failed",
407 address.getIpAddress(), segmentId, e);
410 //delete the entry from snatIntIpportinfo
412 removeFromSnatIpPortDS(segmentId, address.getIpAddress());
413 } catch (Exception e) {
414 LOG.error("releaseAddressMapping : failed, Removal of snatipportmap {} for "
415 + "router {} failed", address.getIpAddress(), segmentId, e);
419 LOG.error("releaseAddressMapping : failed, segmentId {} and internalIpPort {} "
420 + "not found in IpMap DS", segmentId, internalIpPort);
423 // Finally release port from idmanager
424 removePortFromPool(internalIpPort, existingIpPort.getIpAddress());
426 LOG.debug("releaseAddressMapping : Exited successfully for segmentId {} and internalIpPort {}",
427 segmentId, internalIpPort);
431 // TODO Clean up the exception handling
432 @SuppressWarnings("checkstyle:IllegalCatch")
433 protected void releaseIpExtPortMapping(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
434 String internalIpPort = address.getIpAddress() + ":" + address.getPortNumber();
435 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
436 if (existingIpPort != null) {
437 // delete the entry from IpPortMap DS
439 removeFromIpPortMapDS(segmentId, internalIpPort, protocol);
440 // Finally release port from idmanager
441 removePortFromPool(internalIpPort, existingIpPort.getIpAddress());
442 } catch (Exception e) {
443 LOG.error("releaseIpExtPortMapping : failed, Removal of ipportmap {} for "
444 + "router {} failed", internalIpPort, segmentId, e);
447 LOG.error("releaseIpExtPortMapping : failed, segmentId {} and "
448 + "internalIpPort {} not found in IpPortMap DS", segmentId, internalIpPort);
451 //delete the entry of port for InternalIp from snatIntIpportMappingDS
453 removeSnatIntIpPortDS(segmentId, address, protocol);
454 } catch (Exception e) {
455 LOG.error("releaseSnatIpPortMapping : failed, Removal of snatipportmap {} for "
456 + "router {} failed",address.getIpAddress(), segmentId, e);
461 * Removes the internal ip to external ip mapping if present.
463 * @param segmentId - Router ID
464 * @return true if successfully removed
466 // TODO Clean up the exception handling
467 @SuppressWarnings("checkstyle:IllegalCatch")
468 public boolean removeMapping(long segmentId) {
470 removeIpMappingForRouterID(segmentId);
471 removeIpPortMappingForRouterID(segmentId);
472 removeIntIpPortMappingForRouterID(segmentId);
473 } catch (Exception e) {
474 LOG.error("removeMapping : Removal of IPMapping for router {} failed", segmentId, e);
478 //TODO : This is when router is deleted then cleanup the entries in tables, ports etc - Delete scenarios
482 protected InstanceIdentifier<IpMap> getIpMapIdentifier(long segid, String internal) {
483 return InstanceIdentifier.builder(IntextIpMap.class)
484 .child(IpMapping.class, new IpMappingKey(segid))
485 .child(IpMap.class, new IpMapKey(internal)).build();
488 protected InstanceIdentifier<ExternalIpCounter> getExternalIpsIdentifier(long segmentId, String external) {
489 return InstanceIdentifier.builder(ExternalIpsCounter.class)
490 .child(ExternalCounters.class, new ExternalCountersKey(segmentId))
491 .child(ExternalIpCounter.class, new ExternalIpCounterKey(external)).build();
495 public static List<IpMap> getIpMapList(DataBroker broker, Long routerId) {
496 InstanceIdentifier<IpMapping> id = getIpMapList(routerId);
497 return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
498 LogicalDatastoreType.OPERATIONAL, id).toJavaUtil().map(IpMapping::getIpMap).orElse(
499 Collections.emptyList());
502 protected static InstanceIdentifier<IpMapping> getIpMapList(long routerId) {
503 return InstanceIdentifier.builder(
504 IntextIpMap.class).child(IpMapping.class, new IpMappingKey(routerId)).build();
507 protected InstanceIdentifier<IpPortMap> getIpPortMapIdentifier(long segid, String internal,
508 NAPTEntryEvent.Protocol protocol) {
509 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
510 return InstanceIdentifier.builder(IntextIpPortMap.class)
511 .child(IpPortMapping.class, new IpPortMappingKey(segid))
512 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
513 .child(IpPortMap.class, new IpPortMapKey(internal)).build();
516 private SessionAddress checkIpPortMap(long segmentId, String internalIpPort,
517 NAPTEntryEvent.Protocol protocol) {
518 LOG.debug("checkIpPortMap : called with segmentId {} and internalIpPort {}",
519 segmentId, internalIpPort);
520 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
521 // check if ip-port-map node is there
522 InstanceIdentifierBuilder<IpPortMap> idBuilder =
523 InstanceIdentifier.builder(IntextIpPortMap.class)
524 .child(IpPortMapping.class, new IpPortMappingKey(segmentId))
525 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
526 .child(IpPortMap.class, new IpPortMapKey(internalIpPort));
527 InstanceIdentifier<IpPortMap> id = idBuilder.build();
528 Optional<IpPortMap> ipPortMapType =
529 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
530 if (ipPortMapType.isPresent()) {
531 LOG.debug("checkIpPortMap : {}", ipPortMapType.get());
532 SessionAddress externalIpPort = new SessionAddress(ipPortMapType.get().getIpPortExternal().getIpAddress(),
533 ipPortMapType.get().getIpPortExternal().getPortNum());
534 LOG.debug("checkIpPortMap : returning successfully externalIP {} and port {}",
535 externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
536 return externalIpPort;
538 // return null if not found
539 LOG.warn("checkIpPortMap : no-entry in checkIpPortMap, returning NULL [should be OK] for "
540 + "segmentId {} and internalIPPort {}", segmentId, internalIpPort);
544 protected String checkIpMap(long segmentId, String internalIp) {
545 LOG.debug("checkIpMap : called with segmentId {} and internalIp {}", segmentId, internalIp);
547 // check if ip-map node is there
548 InstanceIdentifierBuilder<IpMapping> idBuilder =
549 InstanceIdentifier.builder(IntextIpMap.class).child(IpMapping.class, new IpMappingKey(segmentId));
550 InstanceIdentifier<IpMapping> id = idBuilder.build();
551 Optional<IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
552 if (ipMapping.isPresent()) {
553 List<IpMap> ipMaps = ipMapping.get().getIpMap();
554 for (IpMap ipMap : ipMaps) {
555 if (ipMap.getInternalIp().equals(internalIp)) {
556 LOG.debug("checkIpMap : IpMap : {}", ipMap);
557 externalIp = ipMap.getExternalIp();
558 LOG.debug("checkIpMap : successfully returning externalIp {}", externalIp);
560 } else if (ipMap.getInternalIp().contains("/")) { // subnet case
561 SubnetUtils subnetUtils = new SubnetUtils(ipMap.getInternalIp());
562 SubnetInfo subnetInfo = subnetUtils.getInfo();
563 if (subnetInfo.isInRange(internalIp)) {
564 LOG.debug("checkIpMap : internalIp {} found to be IpMap of internalIpSubnet {}",
565 internalIp, ipMap.getInternalIp());
566 externalIp = ipMap.getExternalIp();
567 LOG.debug("checkIpMap : checkIpMap successfully returning externalIp {}", externalIp);
573 // return null if not found
574 LOG.error("checkIpMap : failed, returning NULL for segmentId {} and internalIp {}",
575 segmentId, internalIp);
579 // TODO Clean up the exception handling
580 @SuppressWarnings("checkstyle:IllegalCatch")
581 protected void removeSnatIntIpPortDS(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
582 LOG.trace("removeSnatIntIpPortDS : method called for IntIpport {} of router {} ",
584 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
585 List<Integer> portList =
586 NatUtil.getInternalIpPortListInfo(dataBroker, segmentId, address.getIpAddress(), protocolType);
587 if (portList.isEmpty() || !portList.contains(address.getPortNumber())) {
588 LOG.error("removeSnatIntIpPortDS : Internal IP {} for port {} entry not found in SnatIntIpPort DS",
589 address.getIpAddress(), address.getPortNumber());
592 LOG.trace("removeSnatIntIpPortDS : PortList {} retrieved for InternalIp {} of router {}",
593 portList, address.getIpAddress(), segmentId);
594 Integer port = address.getPortNumber();
595 portList.remove(port);
597 IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
598 IntIpProtoType intIpProtocolType =
599 builder.withKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
601 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
602 NatUtil.buildSnatIntIpPortIdentifier(segmentId, address.getIpAddress(), protocolType),
604 } catch (Exception ex) {
605 LOG.error("removeSnatIntIpPortDS : Failed to write into snat-internal-ip-port-info with exception", ex);
607 LOG.debug("removeSnatIntIpPortDS : Removing SnatIp {} Port {} of router {} from SNATIntIpport datastore",
608 address.getIpAddress(), address.getPortNumber(), segmentId);
611 protected void removeFromSnatIpPortDS(long segmentId, String internalIp) {
612 InstanceIdentifier<IpPort> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class)
613 .child(IntipPortMap.class, new IntipPortMapKey(segmentId))
614 .child(IpPort.class, new IpPortKey(internalIp)).build();
615 // remove from SnatIpPortDS
616 LOG.debug("removeFromSnatIpPortDS : Removing SnatIpPort from datastore : {}", intIp);
617 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
620 protected void removeFromIpPortMapDS(long segmentId, String internalIpPort, NAPTEntryEvent.Protocol protocol) {
621 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
622 removeFromIpPortMapDS(segmentId, internalIpPort, protocolType);
625 protected void removeFromIpPortMapDS(long segmentId, String internalIpPort, ProtocolTypes protocolType) {
626 InstanceIdentifierBuilder<IpPortMap> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
627 .child(IpPortMapping.class, new IpPortMappingKey(segmentId))
628 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
629 .child(IpPortMap.class, new IpPortMapKey(internalIpPort));
630 InstanceIdentifier<IpPortMap> id = idBuilder.build();
631 // remove from ipportmap DS
632 LOG.debug("removeFromIpPortMapDS : Removing ipportmap from datastore : {}", id);
633 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
636 protected void removeFromIpMapDS(long segmentId, String internalIp) {
637 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
638 .child(IpMapping.class, new IpMappingKey(segmentId))
639 .child(IpMap.class, new IpMapKey(internalIp));
640 InstanceIdentifier<IpMap> id = idBuilder.build();
641 // Get externalIp and decrement the counter
642 String externalIp = null;
643 Optional<IpMap> ipMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
644 if (ipMap.isPresent()) {
645 externalIp = ipMap.get().getExternalIp();
646 LOG.debug("removeFromIpMapDS : externalIP is {}", externalIp);
648 LOG.warn("removeFromIpMapDS : ipMap not present for the internal IP {}", internalIp);
651 if (externalIp != null) {
652 updateCounter(segmentId, externalIp, false);
653 // remove from ipmap DS
654 LOG.debug("removeFromIpMapDS : Removing ipmap from datastore");
655 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
657 LOG.warn("removeFromIpMapDS : externalIp not present for the internal IP {}", internalIp);
661 protected void removeIntExtIpMapDS(long segmentId, String internalIp) {
662 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
663 .child(IpMapping.class, new IpMappingKey(segmentId))
664 .child(IpMap.class, new IpMapKey(internalIp));
665 InstanceIdentifier<IpMap> id = idBuilder.build();
667 LOG.debug("removeIntExtIpMapDS : Removing ipmap from datastore");
668 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
671 protected String getExternalIpAllocatedForSubnet(long segmentId, String internalIp) {
672 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
673 .child(IpMapping.class, new IpMappingKey(segmentId))
674 .child(IpMap.class, new IpMapKey(internalIp));
675 InstanceIdentifier<IpMap> id = idBuilder.build();
677 Optional<IpMap> ipMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
678 if (ipMap.isPresent()) {
679 return ipMap.get().getExternalIp();
684 private void removeIpMappingForRouterID(long segmentId) {
685 InstanceIdentifierBuilder<IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
686 .child(IpMapping.class, new IpMappingKey(segmentId));
687 InstanceIdentifier<IpMapping> id = idBuilder.build();
688 // Get all externalIps and decrement their counters before deleting the ipmap
689 String externalIp = null;
690 Optional<IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
691 if (ipMapping.isPresent()) {
692 List<IpMap> ipMaps = ipMapping.get().getIpMap();
693 for (IpMap ipMap : ipMaps) {
694 externalIp = ipMap.getExternalIp();
695 LOG.debug("removeIpMappingForRouterID : externalIP is {}", externalIp);
696 if (externalIp != null) {
697 updateCounter(segmentId, externalIp, false);
700 // remove from ipmap DS
701 LOG.debug("removeIpMappingForRouterID : Removing Ipmap for router {} from datastore", segmentId);
702 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
706 void removeIpPortMappingForRouterID(long segmentId) {
707 InstanceIdentifier<IpPortMapping> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
708 .child(IpPortMapping.class, new IpPortMappingKey(segmentId)).build();
709 Optional<IpPortMapping> ipPortMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
711 if (ipPortMapping.isPresent()) {
712 // remove from IntExtIpPortmap DS
713 LOG.debug("removeIpPortMappingForRouterID : Removing IntExtIpPort map for router {} from datastore",
715 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, idBuilder);
719 void removeIntIpPortMappingForRouterID(long segmentId) {
720 InstanceIdentifier<IntipPortMap> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class)
721 .child(IntipPortMap.class, new IntipPortMapKey(segmentId)).build();
722 Optional<IntipPortMap> intIpPortMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
723 if (intIpPortMap.isPresent()) {
724 // remove from SnatIntIpPortmap DS
725 LOG.debug("removeIntIpPortMappingForRouterID : Removing SnatIntIpPort from datastore : {}", intIp);
726 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
730 void removePortFromPool(String internalIpPort, String externalIp) {
731 LOG.debug("removePortFromPool : method called");
732 ReleaseIdInput idInput = new ReleaseIdInputBuilder()
733 .setPoolName(externalIp)
734 .setIdKey(internalIpPort).build();
736 RpcResult<ReleaseIdOutput> rpcResult = idManager.releaseId(idInput).get();
737 if (!rpcResult.isSuccessful()) {
738 LOG.error("removePortFromPool : idmanager failed to remove port from pool {}", rpcResult.getErrors());
740 LOG.debug("removePortFromPool : Removed port from pool for InternalIpPort {} with externalIp {}",
741 internalIpPort, externalIp);
742 } catch (InterruptedException | ExecutionException e) {
743 LOG.error("removePortFromPool : idmanager failed when removing entry in pool with key {} with Exception",
748 protected void initialiseExternalCounter(Routers routers, long routerId) {
749 LOG.debug("initialiseExternalCounter : Initialise External IPs counter");
750 List<ExternalIps> externalIps = routers.getExternalIps();
752 //update the new counter value for this externalIp
753 for (ExternalIps externalIp : externalIps) {
754 String[] ipSplit = externalIp.getIpAddress().split("/");
755 String extIp = ipSplit[0];
756 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
757 if (ipSplit.length == 2) {
758 extPrefix = ipSplit[1];
760 extIp = extIp + "/" + extPrefix;
761 initialiseNewExternalIpCounter(routerId, extIp);
765 protected void initialiseNewExternalIpCounter(long routerId, String externalIp) {
766 ExternalIpCounter externalIpCounterData = new ExternalIpCounterBuilder()
767 .withKey(new ExternalIpCounterKey(externalIp)).setExternalIp(externalIp).setCounter((short) 0).build();
768 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
769 getExternalIpsIdentifier(routerId, externalIp), externalIpCounterData);
772 protected void removeExternalCounter(long routerId) {
773 // Remove from external-counters model
774 InstanceIdentifier<ExternalCounters> id = InstanceIdentifier.builder(ExternalIpsCounter.class)
775 .child(ExternalCounters.class, new ExternalCountersKey(routerId)).build();
776 LOG.debug("removeExternalCounter : Removing ExternalCounterd from datastore");
777 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
780 protected void removeExternalIpCounter(long routerId, String externalIp) {
781 // Remove from external-counters model
782 InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class)
783 .child(ExternalCounters.class, new ExternalCountersKey(routerId))
784 .child(ExternalIpCounter.class, new ExternalIpCounterKey(externalIp)).build();
785 LOG.debug("removeExternalIpCounter : Removing ExternalIpsCounter from datastore");
786 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);