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.util.concurrent.UncheckedExecutionException;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.Collections;
18 import java.util.List;
19 import java.util.Objects;
20 import java.util.Optional;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.Future;
23 import java.util.concurrent.locks.ReentrantLock;
24 import javax.inject.Inject;
25 import javax.inject.Singleton;
26 import org.apache.commons.net.util.SubnetUtils;
27 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
28 import org.eclipse.jdt.annotation.NonNull;
29 import org.eclipse.jdt.annotation.Nullable;
30 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
31 import org.opendaylight.genius.mdsalutil.MDSALUtil;
32 import org.opendaylight.genius.utils.JvmGlobalLocks;
33 import org.opendaylight.mdsal.binding.api.DataBroker;
34 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInputBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolOutput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpMap;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.SnatintIpPortMap;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCountersKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounterBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounterKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMappingKey;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolTypeKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapKey;
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.IpPortExternal;
67 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;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMap;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMapKey;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPortKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeKey;
75 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
76 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
77 import org.opendaylight.yangtools.yang.common.RpcResult;
78 import org.opendaylight.yangtools.yang.common.Uint16;
79 import org.opendaylight.yangtools.yang.common.Uint32;
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(Uint32 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(Uint32 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 = Optional.empty();
189 externalIpCounter = SingleTransactionDataBroker.syncReadOptional(dataBroker,
190 LogicalDatastoreType.OPERATIONAL, id);
191 } catch (ExecutionException | InterruptedException e) {
192 LOG.error("updateCounter: Exception while reading ExternalIpCounter DS for the segmentId {} externalIp {} ",
193 segmentId, externalIp, e);
195 if (externalIpCounter.isPresent()) {
196 counter = externalIpCounter.get().getCounter().toJava();
199 LOG.debug("updateCounter : externalIp and counter after increment are {} and {}", externalIp, counter);
204 LOG.debug("updateCounter : externalIp and counter after decrement are {} and {}", externalIp, counter);
211 //update the new counter value for this externalIp
212 ExternalIpCounter externalIpCounterData = new ExternalIpCounterBuilder()
213 .withKey(new ExternalIpCounterKey(externalIp)).setExternalIp(externalIp).setCounter(counter).build();
214 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
215 getExternalIpsIdentifier(segmentId, externalIp), externalIpCounterData);
219 * method to get external ip/port mapping when provided with internal ip/port pair
220 * If already a mapping exist for the given input, then the existing mapping is returned
221 * instead of overwriting with new ip/port pair.
223 * @param segmentId - Router ID
224 * @param sourceAddress - internal ip address/port pair
225 * @param protocol - TCP/UDP
226 * @return external ip address/port
228 // TODO Clean up the exception handling
229 @SuppressWarnings("checkstyle:IllegalCatch")
231 public SessionAddress getExternalAddressMapping(Uint32 segmentId, SessionAddress sourceAddress,
232 NAPTEntryEvent.Protocol protocol) {
233 LOG.debug("getExternalAddressMapping : called with segmentId {}, internalIp {} and port {}",
234 segmentId, sourceAddress.getIpAddress(), sourceAddress.getPortNumber());
236 1. Get Internal IP, Port in IP:Port format
237 2. Inside DB with routerId get the list of entries and check if it matches with existing IP:Port
238 3. If True return SessionAddress of ExternalIp and Port
239 4. Else check ip Map and Form the ExternalIp and Port and update DB and then return ExternalIp and Port
242 //SessionAddress externalIpPort = new SessionAddress();
243 String internalIpPort = sourceAddress.getIpAddress() + ":" + sourceAddress.getPortNumber();
245 // First check existing Port Map.
246 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
247 if (existingIpPort != null) {
248 // populate externalIpPort from IpPortMap and return
249 LOG.debug("getExternalAddressMapping : successfully returning existingIpPort as {} and {}",
250 existingIpPort.getIpAddress(), existingIpPort.getPortNumber());
251 return existingIpPort;
254 // Now check in ip-map
255 String externalIp = checkIpMap(segmentId, sourceAddress.getIpAddress());
256 if (externalIp == null) {
257 LOG.error("getExternalAddressMapping : Unexpected error, internal to external "
258 + "ip map does not exist");
262 /* Logic assuming internalIp is always ip and not subnet
263 * case 1: externalIp is ip
264 * a) goto externalIp pool and getPort and return
265 * b) else return error
266 * case 2: externalIp is subnet
267 * a) Take first externalIp and goto that Pool and getPort
269 * else Take second externalIp and create that Pool and getPort
272 * Continue same with third externalIp till we exhaust subnet
273 * b) Nothing worked return error
275 SubnetUtils externalIpSubnet;
276 List<String> allIps = new ArrayList<>();
277 String subnetPrefix = "/" + String.valueOf(NatConstants.DEFAULT_PREFIX);
278 boolean extSubnetFlag = false;
279 if (!externalIp.contains(subnetPrefix)) {
280 extSubnetFlag = true;
281 externalIpSubnet = new SubnetUtils(externalIp);
282 allIps = Arrays.asList(externalIpSubnet.getInfo().getAllAddresses());
283 LOG.debug("getExternalAddressMapping : total count of externalIps available {}",
284 externalIpSubnet.getInfo().getAddressCount());
286 LOG.debug("getExternalAddressMapping : getExternalAddress single ip case");
287 if (externalIp.contains(subnetPrefix)) {
288 //remove /32 what we got from checkIpMap
289 externalIp = externalIp.substring(0, externalIp.indexOf(subnetPrefix));
291 allIps.add(externalIp);
294 boolean nextExtIpFlag = false;
295 for (String extIp : allIps) {
296 LOG.info("getExternalAddressMapping : Looping externalIPs with externalIP now as {}", extIp);
298 createNaptPortPool(extIp);
299 LOG.debug("getExternalAddressMapping : Created Pool for next Ext IP {}", extIp);
301 Uint32 extPort = NatUtil.getUniqueId(idManager, extIp, internalIpPort);
302 if (extPort == NatConstants.INVALID_ID) {
303 LOG.error("getExternalAddressMapping : getExternalAddressMapping, idManager could not "
304 + "allocate id retry if subnet");
305 if (!extSubnetFlag) {
306 LOG.error("getExternalAddressMapping : getExternalAddressMapping returning null "
307 + "for single IP case, may be ports exhausted");
310 LOG.debug("getExternalAddressMapping : Could be ports exhausted case, "
311 + "try with another externalIP if possible");
312 nextExtIpFlag = true;
315 // Write to ip-port-map before returning
316 IpPortExternalBuilder ipExt = new IpPortExternalBuilder();
317 IpPortExternal ipPortExt = ipExt.setIpAddress(extIp).setPortNum(extPort.intValue()).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 final ReentrantLock lock = lockFor(segmentId, internalIpAddress, protocolType);
338 List<Uint16> portList = new ArrayList<>(
339 NatUtil.getInternalIpPortListInfo(dataBroker, segmentId, internalIpAddress,
341 portList.add(Uint16.valueOf(ipPort));
343 IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
344 IntIpProtoType intIpProtocolType =
345 builder.withKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
347 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
348 NatUtil.buildSnatIntIpPortIdentifier(segmentId, internalIpAddress, protocolType),
350 } catch (Exception ex) {
351 LOG.error("getExternalAddressMapping : Failed to write into snat-internal-ip-port-info "
352 + "with exception", ex);
357 SessionAddress externalIpPort = new SessionAddress(extIp, extPort.intValue());
358 LOG.debug("getExternalAddressMapping : successfully returning externalIP {} "
359 + "and port {}", externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
360 return externalIpPort;
362 LOG.error("getExternalAddressMapping : Unable to handle external IP address and port mapping with segmentId {},"
363 + "internalIp {} and internalPort {}", segmentId, sourceAddress.getIpAddress(),
364 sourceAddress.getPortNumber());
368 // TODO Clean up the exception handling
369 @SuppressWarnings("checkstyle:IllegalCatch")
370 protected void releaseIpExtPortMapping(Uint32 segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
371 String internalIpPort = address.getIpAddress() + ":" + address.getPortNumber();
372 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
373 if (existingIpPort != null) {
374 // delete the entry from IpPortMap DS
376 removeFromIpPortMapDS(segmentId, internalIpPort, protocol);
377 // Finally release port from idmanager
378 Uint32 releasedId = NatUtil.releaseId(idManager, existingIpPort.getIpAddress(), internalIpPort);
379 if (releasedId == NatConstants.INVALID_ID) {
380 LOG.error("releaseIpExtPortMapping : Unable to release ID for key {}",
381 existingIpPort.getIpAddress());
383 } catch (Exception e) {
384 LOG.error("releaseIpExtPortMapping : failed, Removal of ipportmap {} for "
385 + "router {} failed", internalIpPort, segmentId, e);
388 LOG.error("releaseIpExtPortMapping : failed, segmentId {} and "
389 + "internalIpPort {} not found in IpPortMap DS", segmentId, internalIpPort);
392 //delete the entry of port for InternalIp from snatIntIpportMappingDS
393 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
394 final ReentrantLock lock = lockFor(segmentId, address.getIpAddress(), protocolType);
397 removeSnatIntIpPortDS(segmentId, address, protocolType);
398 } catch (Exception e) {
399 LOG.error("releaseSnatIpPortMapping : failed, Removal of snatipportmap {} for router {} failed",
400 address.getIpAddress(), segmentId, e);
407 * Removes the internal ip to external ip mapping if present.
409 * @param segmentId - Router ID
410 * @return true if successfully removed
412 // TODO Clean up the exception handling
413 @SuppressWarnings("checkstyle:IllegalCatch")
414 public boolean removeMapping(Uint32 segmentId) {
416 removeIpMappingForRouterID(segmentId);
417 removeIpPortMappingForRouterID(segmentId);
418 removeIntIpPortMappingForRouterID(segmentId);
419 } catch (Exception e) {
420 LOG.error("removeMapping : Removal of IPMapping for router {} failed", segmentId, e);
424 //TODO : This is when router is deleted then cleanup the entries in tables, ports etc - Delete scenarios
428 protected InstanceIdentifier<IpMap> getIpMapIdentifier(Uint32 segid, String internal) {
429 return InstanceIdentifier.builder(IntextIpMap.class)
430 .child(IpMapping.class, new IpMappingKey(segid))
431 .child(IpMap.class, new IpMapKey(internal)).build();
434 protected InstanceIdentifier<ExternalIpCounter> getExternalIpsIdentifier(Uint32 segmentId, String external) {
435 return InstanceIdentifier.builder(ExternalIpsCounter.class)
436 .child(ExternalCounters.class, new ExternalCountersKey(segmentId))
437 .child(ExternalIpCounter.class, new ExternalIpCounterKey(external)).build();
441 public static List<IpMap> getIpMapList(DataBroker broker, Uint32 routerId) {
442 InstanceIdentifier<IpMapping> id = getIpMapList(routerId);
443 return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
444 LogicalDatastoreType.OPERATIONAL, id).map(IpMapping::getIpMap).orElse(
445 Collections.emptyList());
448 protected static InstanceIdentifier<IpMapping> getIpMapList(Uint32 routerId) {
449 return InstanceIdentifier.builder(
450 IntextIpMap.class).child(IpMapping.class, new IpMappingKey(routerId)).build();
453 protected InstanceIdentifier<IpPortMap> getIpPortMapIdentifier(Uint32 segid, String internal,
454 NAPTEntryEvent.Protocol protocol) {
455 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
456 return InstanceIdentifier.builder(IntextIpPortMap.class)
457 .child(IpPortMapping.class, new IpPortMappingKey(segid))
458 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
459 .child(IpPortMap.class, new IpPortMapKey(internal)).build();
463 private SessionAddress checkIpPortMap(Uint32 segmentId, String internalIpPort,
464 NAPTEntryEvent.Protocol protocol) {
465 LOG.debug("checkIpPortMap : called with segmentId {} and internalIpPort {}",
466 segmentId, internalIpPort);
467 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
468 // check if ip-port-map node is there
469 InstanceIdentifierBuilder<IpPortMap> idBuilder =
470 InstanceIdentifier.builder(IntextIpPortMap.class)
471 .child(IpPortMapping.class, new IpPortMappingKey(segmentId))
472 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
473 .child(IpPortMap.class, new IpPortMapKey(internalIpPort));
474 InstanceIdentifier<IpPortMap> id = idBuilder.build();
475 Optional<IpPortMap> ipPortMapType = Optional.empty();
477 ipPortMapType = SingleTransactionDataBroker.syncReadOptional(dataBroker,
478 LogicalDatastoreType.CONFIGURATION, id);
479 } catch (ExecutionException | InterruptedException e) {
480 LOG.error("checkIpPortMap: Exception while reading IpMap DS for the segmentId {} "
481 + "internalIpPort {} protocol {}", segmentId, internalIpPort, protocol, e);
483 if (ipPortMapType.isPresent()) {
484 LOG.debug("checkIpPortMap : {}", ipPortMapType.get());
485 SessionAddress externalIpPort = new SessionAddress(ipPortMapType.get().getIpPortExternal().getIpAddress(),
486 ipPortMapType.get().getIpPortExternal().getPortNum().toJava());
487 LOG.debug("checkIpPortMap : returning successfully externalIP {} and port {}",
488 externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
489 return externalIpPort;
491 // return null if not found
492 LOG.warn("checkIpPortMap : no-entry in checkIpPortMap, returning NULL [should be OK] for "
493 + "segmentId {} and internalIPPort {}", segmentId, internalIpPort);
498 protected String checkIpMap(Uint32 segmentId, String internalIp) {
499 LOG.debug("checkIpMap : called with segmentId {} and internalIp {}", segmentId, internalIp);
501 // check if ip-map node is there
502 InstanceIdentifierBuilder<IpMapping> idBuilder =
503 InstanceIdentifier.builder(IntextIpMap.class).child(IpMapping.class, new IpMappingKey(segmentId));
504 InstanceIdentifier<IpMapping> id = idBuilder.build();
505 Optional<IpMapping> ipMapping = Optional.empty();
507 ipMapping = SingleTransactionDataBroker.syncReadOptional(dataBroker,
508 LogicalDatastoreType.OPERATIONAL, id);
509 } catch (ExecutionException | InterruptedException e) {
510 LOG.error("checkIpMap: Exception while reading IpMapping DS for the segmentId {} internalIp {}",
511 segmentId, internalIp, e);
513 if (ipMapping.isPresent()) {
514 for (IpMap ipMap : ipMapping.get().nonnullIpMap()) {
515 if (Objects.equals(ipMap.getInternalIp(), internalIp)) {
516 LOG.debug("checkIpMap : IpMap : {}", ipMap);
517 externalIp = ipMap.getExternalIp();
518 LOG.debug("checkIpMap : successfully returning externalIp {}", externalIp);
520 } else if (ipMap.getInternalIp().contains("/")) { // subnet case
521 SubnetUtils subnetUtils = new SubnetUtils(ipMap.getInternalIp());
522 SubnetInfo subnetInfo = subnetUtils.getInfo();
523 if (subnetInfo.isInRange(internalIp)) {
524 LOG.debug("checkIpMap : internalIp {} found to be IpMap of internalIpSubnet {}",
525 internalIp, ipMap.getInternalIp());
526 externalIp = ipMap.getExternalIp();
527 LOG.debug("checkIpMap : checkIpMap successfully returning externalIp {}", externalIp);
533 // return null if not found
534 LOG.error("checkIpMap : failed, returning NULL for segmentId {} and internalIp {}",
535 segmentId, internalIp);
539 // TODO Clean up the exception handling
540 @SuppressWarnings("checkstyle:IllegalCatch")
541 protected void removeSnatIntIpPortDS(Uint32 segmentId, SessionAddress address, ProtocolTypes protocolType) {
542 LOG.trace("removeSnatIntIpPortDS : method called for IntIpport {} of router {} ",
544 List<Uint16> portList =
545 NatUtil.getInternalIpPortListInfo(dataBroker, segmentId, address.getIpAddress(), protocolType);
546 if (portList.isEmpty() || !portList.contains(Uint16.valueOf(address.getPortNumber()))) {
547 LOG.error("removeSnatIntIpPortDS : Internal IP {} for port {} entry not found in SnatIntIpPort DS",
548 address.getIpAddress(), address.getPortNumber());
551 LOG.trace("removeSnatIntIpPortDS : PortList {} retrieved for InternalIp {} of router {}",
552 portList, address.getIpAddress(), segmentId);
553 Integer port = address.getPortNumber();
554 portList.remove(Uint16.valueOf(port));
556 IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
557 IntIpProtoType intIpProtocolType =
558 builder.withKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
560 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
561 NatUtil.buildSnatIntIpPortIdentifier(segmentId, address.getIpAddress(), protocolType),
563 } catch (Exception ex) {
564 LOG.error("removeSnatIntIpPortDS : Failed to write into snat-internal-ip-port-info with exception", ex);
566 LOG.debug("removeSnatIntIpPortDS : Removing SnatIp {} Port {} of router {} from SNATIntIpport datastore",
567 address.getIpAddress(), address.getPortNumber(), segmentId);
570 protected void removeFromSnatIpPortDS(Uint32 segmentId, String internalIp) {
571 InstanceIdentifier<IpPort> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class)
572 .child(IntipPortMap.class, new IntipPortMapKey(segmentId))
573 .child(IpPort.class, new IpPortKey(internalIp)).build();
574 // remove from SnatIpPortDS
575 LOG.debug("removeFromSnatIpPortDS : Removing SnatIpPort from datastore : {}", intIp);
576 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
579 protected void removeFromIpPortMapDS(Uint32 segmentId, String internalIpPort, NAPTEntryEvent.Protocol protocol) {
580 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
581 removeFromIpPortMapDS(segmentId, internalIpPort, protocolType);
584 protected void removeFromIpPortMapDS(Uint32 segmentId, String internalIpPort, ProtocolTypes protocolType) {
585 InstanceIdentifierBuilder<IpPortMap> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
586 .child(IpPortMapping.class, new IpPortMappingKey(segmentId))
587 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
588 .child(IpPortMap.class, new IpPortMapKey(internalIpPort));
589 InstanceIdentifier<IpPortMap> id = idBuilder.build();
590 // remove from ipportmap DS
591 LOG.debug("removeFromIpPortMapDS : Removing ipportmap from datastore : {}", id);
592 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
595 protected void removeFromIpMapDS(Uint32 segmentId, String internalIp) {
596 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
597 .child(IpMapping.class, new IpMappingKey(segmentId))
598 .child(IpMap.class, new IpMapKey(internalIp));
599 InstanceIdentifier<IpMap> id = idBuilder.build();
600 // Get externalIp and decrement the counter
601 String externalIp = null;
602 Optional<IpMap> ipMap = Optional.empty();
604 ipMap = SingleTransactionDataBroker.syncReadOptional(dataBroker,
605 LogicalDatastoreType.OPERATIONAL, id);
606 } catch (ExecutionException | InterruptedException e) {
607 LOG.error("removeFromIpMapDS: Exception while reading IpMap DS for the segmentId {} "
608 + "internalIp {}", segmentId, internalIp, e);
610 if (ipMap.isPresent()) {
611 externalIp = ipMap.get().getExternalIp();
612 LOG.debug("removeFromIpMapDS : externalIP is {}", externalIp);
614 LOG.warn("removeFromIpMapDS : ipMap not present for the internal IP {}", internalIp);
617 if (externalIp != null) {
618 updateCounter(segmentId, externalIp, false);
619 // remove from ipmap DS
620 LOG.debug("removeFromIpMapDS : Removing ipmap from datastore");
621 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
623 LOG.warn("removeFromIpMapDS : externalIp not present for the internal IP {}", internalIp);
627 protected void removeIntExtIpMapDS(Uint32 segmentId, String internalIp) {
628 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
629 .child(IpMapping.class, new IpMappingKey(segmentId))
630 .child(IpMap.class, new IpMapKey(internalIp));
631 InstanceIdentifier<IpMap> id = idBuilder.build();
633 LOG.debug("removeIntExtIpMapDS : Removing ipmap from datastore");
634 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
638 protected String getExternalIpAllocatedForSubnet(Uint32 segmentId, String internalIp) {
639 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
640 .child(IpMapping.class, new IpMappingKey(segmentId))
641 .child(IpMap.class, new IpMapKey(internalIp));
642 InstanceIdentifier<IpMap> id = idBuilder.build();
644 Optional<IpMap> ipMap;
646 ipMap = SingleTransactionDataBroker.syncReadOptional(dataBroker,
647 LogicalDatastoreType.OPERATIONAL, id);
648 } catch (ExecutionException | InterruptedException e) {
649 LOG.error("getExternalIpAllocatedForSubnet: Exception while reading IpMap DS for the segmentId {} "
650 + "internalIp {}", segmentId, internalIp, e);
653 if (ipMap.isPresent()) {
654 return ipMap.get().getExternalIp();
659 private void removeIpMappingForRouterID(Uint32 segmentId) {
660 InstanceIdentifierBuilder<IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
661 .child(IpMapping.class, new IpMappingKey(segmentId));
662 InstanceIdentifier<IpMapping> id = idBuilder.build();
663 // Get all externalIps and decrement their counters before deleting the ipmap
664 Optional<IpMapping> ipMapping = Optional.empty();
666 ipMapping = SingleTransactionDataBroker.syncReadOptional(dataBroker,
667 LogicalDatastoreType.OPERATIONAL, id);
668 } catch (ExecutionException | InterruptedException e) {
669 LOG.error("removeIpMappingForRouterID: Exception while reading IpMapping DS for the segmentId {} ",
672 if (ipMapping.isPresent()) {
673 for (IpMap ipMap : ipMapping.get().nonnullIpMap()) {
674 String externalIp = ipMap.getExternalIp();
675 LOG.debug("removeIpMappingForRouterID : externalIP is {}", externalIp);
676 if (externalIp != null) {
677 updateCounter(segmentId, externalIp, false);
680 // remove from ipmap DS
681 LOG.debug("removeIpMappingForRouterID : Removing Ipmap for router {} from datastore", segmentId);
682 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
686 void removeIpPortMappingForRouterID(Uint32 segmentId) {
687 InstanceIdentifier<IpPortMapping> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
688 .child(IpPortMapping.class, new IpPortMappingKey(segmentId)).build();
689 Optional<IpPortMapping> ipPortMapping = Optional.empty();
691 ipPortMapping = SingleTransactionDataBroker.syncReadOptional(dataBroker,
692 LogicalDatastoreType.CONFIGURATION, idBuilder);
693 } catch (ExecutionException | InterruptedException e) {
694 LOG.error("removeIpPortMappingForRouterID: Exception while reading IpPortMapping DS for the segmentId {} ",
697 if (ipPortMapping.isPresent()) {
698 // remove from IntExtIpPortmap DS
699 LOG.debug("removeIpPortMappingForRouterID : Removing IntExtIpPort map for router {} from datastore",
701 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, idBuilder);
705 void removeIntIpPortMappingForRouterID(Uint32 segmentId) {
706 InstanceIdentifier<IntipPortMap> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class)
707 .child(IntipPortMap.class, new IntipPortMapKey(segmentId)).build();
708 Optional<IntipPortMap> intIpPortMap = Optional.empty();
710 intIpPortMap = SingleTransactionDataBroker.syncReadOptional(dataBroker,
711 LogicalDatastoreType.CONFIGURATION, intIp);
712 } catch (ExecutionException | InterruptedException e) {
713 LOG.error("removeIntIpPortMappingForRouterID: Exception while reading IntipPortMap DS for the "
714 + "segmentId {} ", segmentId, e);
716 if (intIpPortMap.isPresent()) {
717 // remove from SnatIntIpPortmap DS
718 LOG.debug("removeIntIpPortMappingForRouterID : Removing SnatIntIpPort from datastore : {}", intIp);
719 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
723 void removePortFromPool(String internalIpPort, String externalIp) {
724 if (NatUtil.releaseId(idManager, externalIp, internalIpPort) == NatConstants.INVALID_ID) {
725 LOG.error("Unable to release id {} from Pool {}", internalIpPort, externalIp);
729 protected void initialiseExternalCounter(Routers routers, Uint32 routerId) {
730 LOG.debug("initialiseExternalCounter : Initialise External IPs counter");
732 //update the new counter value for this externalIp
733 for (ExternalIps externalIp : routers.nonnullExternalIps()) {
734 String[] ipSplit = externalIp.getIpAddress().split("/");
735 String extIp = ipSplit[0];
736 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
737 if (ipSplit.length == 2) {
738 extPrefix = ipSplit[1];
740 extIp = extIp + "/" + extPrefix;
741 initialiseNewExternalIpCounter(routerId, extIp);
745 protected void initialiseNewExternalIpCounter(Uint32 routerId, String externalIp) {
746 ExternalIpCounter externalIpCounterData = new ExternalIpCounterBuilder()
747 .withKey(new ExternalIpCounterKey(externalIp)).setExternalIp(externalIp).setCounter((short) 0).build();
748 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
749 getExternalIpsIdentifier(routerId, externalIp), externalIpCounterData);
752 protected void removeExternalCounter(Uint32 routerId) {
753 // Remove from external-counters model
754 InstanceIdentifier<ExternalCounters> id = InstanceIdentifier.builder(ExternalIpsCounter.class)
755 .child(ExternalCounters.class, new ExternalCountersKey(routerId)).build();
756 LOG.debug("removeExternalCounter : Removing ExternalCounterd from datastore");
757 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
760 protected void removeExternalIpCounter(Uint32 routerId, String externalIp) {
761 // Remove from external-counters model
762 InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class)
763 .child(ExternalCounters.class, new ExternalCountersKey(routerId))
764 .child(ExternalIpCounter.class, new ExternalIpCounterKey(externalIp)).build();
765 LOG.debug("removeExternalIpCounter : Removing ExternalIpsCounter from datastore");
766 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
769 private static ReentrantLock lockFor(final Uint32 segmentId, String ipAddress, final ProtocolTypes protocolType) {
770 // FIXME: use an Identifier class instead?
771 String lockName = new StringBuilder()
773 .append(NatConstants.COLON_SEPARATOR)
775 .append(NatConstants.COLON_SEPARATOR)
776 .append(protocolType.getName()).toString();
778 return JvmGlobalLocks.getLockForString(lockName);