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.Objects;
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.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
32 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
33 import org.opendaylight.genius.mdsalutil.MDSALUtil;
34 import org.opendaylight.genius.utils.JvmGlobalLocks;
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 =
188 MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
189 if (externalIpCounter.isPresent()) {
190 counter = externalIpCounter.get().getCounter().toJava();
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")
225 public SessionAddress getExternalAddressMapping(Uint32 segmentId, SessionAddress sourceAddress,
226 NAPTEntryEvent.Protocol protocol) {
227 LOG.debug("getExternalAddressMapping : called with segmentId {}, internalIp {} and port {}",
228 segmentId, sourceAddress.getIpAddress(), sourceAddress.getPortNumber());
230 1. Get Internal IP, Port in IP:Port format
231 2. Inside DB with routerId get the list of entries and check if it matches with existing IP:Port
232 3. If True return SessionAddress of ExternalIp and Port
233 4. Else check ip Map and Form the ExternalIp and Port and update DB and then return ExternalIp and Port
236 //SessionAddress externalIpPort = new SessionAddress();
237 String internalIpPort = sourceAddress.getIpAddress() + ":" + sourceAddress.getPortNumber();
239 // First check existing Port Map.
240 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
241 if (existingIpPort != null) {
242 // populate externalIpPort from IpPortMap and return
243 LOG.debug("getExternalAddressMapping : successfully returning existingIpPort as {} and {}",
244 existingIpPort.getIpAddress(), existingIpPort.getPortNumber());
245 return existingIpPort;
248 // Now check in ip-map
249 String externalIp = checkIpMap(segmentId, sourceAddress.getIpAddress());
250 if (externalIp == null) {
251 LOG.error("getExternalAddressMapping : Unexpected error, internal to external "
252 + "ip map does not exist");
256 /* Logic assuming internalIp is always ip and not subnet
257 * case 1: externalIp is ip
258 * a) goto externalIp pool and getPort and return
259 * b) else return error
260 * case 2: externalIp is subnet
261 * a) Take first externalIp and goto that Pool and getPort
263 * else Take second externalIp and create that Pool and getPort
266 * Continue same with third externalIp till we exhaust subnet
267 * b) Nothing worked return error
269 SubnetUtils externalIpSubnet;
270 List<String> allIps = new ArrayList<>();
271 String subnetPrefix = "/" + String.valueOf(NatConstants.DEFAULT_PREFIX);
272 boolean extSubnetFlag = false;
273 if (!externalIp.contains(subnetPrefix)) {
274 extSubnetFlag = true;
275 externalIpSubnet = new SubnetUtils(externalIp);
276 allIps = Arrays.asList(externalIpSubnet.getInfo().getAllAddresses());
277 LOG.debug("getExternalAddressMapping : total count of externalIps available {}",
278 externalIpSubnet.getInfo().getAddressCount());
280 LOG.debug("getExternalAddressMapping : getExternalAddress single ip case");
281 if (externalIp.contains(subnetPrefix)) {
282 //remove /32 what we got from checkIpMap
283 externalIp = externalIp.substring(0, externalIp.indexOf(subnetPrefix));
285 allIps.add(externalIp);
288 boolean nextExtIpFlag = false;
289 for (String extIp : allIps) {
290 LOG.info("getExternalAddressMapping : Looping externalIPs with externalIP now as {}", extIp);
292 createNaptPortPool(extIp);
293 LOG.debug("getExternalAddressMapping : Created Pool for next Ext IP {}", extIp);
295 Uint32 extPort = NatUtil.getUniqueId(idManager, extIp, internalIpPort);
296 if (extPort == NatConstants.INVALID_ID) {
297 LOG.error("getExternalAddressMapping : getExternalAddressMapping, idManager could not "
298 + "allocate id retry if subnet");
299 if (!extSubnetFlag) {
300 LOG.error("getExternalAddressMapping : getExternalAddressMapping returning null "
301 + "for single IP case, may be ports exhausted");
304 LOG.debug("getExternalAddressMapping : Could be ports exhausted case, "
305 + "try with another externalIP if possible");
306 nextExtIpFlag = true;
309 // Write to ip-port-map before returning
310 IpPortExternalBuilder ipExt = new IpPortExternalBuilder();
311 IpPortExternal ipPortExt = ipExt.setIpAddress(extIp).setPortNum(extPort.intValue()).build();
312 IpPortMap ipm = new IpPortMapBuilder().withKey(new IpPortMapKey(internalIpPort))
313 .setIpPortInternal(internalIpPort).setIpPortExternal(ipPortExt).build();
314 LOG.debug("getExternalAddressMapping : writing into ip-port-map with "
315 + "externalIP {} and port {}",
316 ipPortExt.getIpAddress(), ipPortExt.getPortNum());
318 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
319 getIpPortMapIdentifier(segmentId, internalIpPort, protocol), ipm);
320 } catch (UncheckedExecutionException uee) {
321 LOG.error("getExternalAddressMapping : Failed to write into ip-port-map with exception",
325 // Write to snat-internal-ip-port-info
326 String internalIpAddress = sourceAddress.getIpAddress();
327 int ipPort = sourceAddress.getPortNumber();
328 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
329 final ReentrantLock lock = lockFor(segmentId, internalIpAddress, protocolType);
332 List<Uint16> portList = new ArrayList<>(
333 NatUtil.getInternalIpPortListInfo(dataBroker, segmentId, internalIpAddress,
335 portList.add(Uint16.valueOf(ipPort));
337 IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
338 IntIpProtoType intIpProtocolType =
339 builder.withKey(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);
351 SessionAddress externalIpPort = new SessionAddress(extIp, extPort.intValue());
352 LOG.debug("getExternalAddressMapping : successfully returning externalIP {} "
353 + "and port {}", externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
354 return externalIpPort;
356 LOG.error("getExternalAddressMapping : Unable to handle external IP address and port mapping with segmentId {},"
357 + "internalIp {} and internalPort {}", segmentId, sourceAddress.getIpAddress(),
358 sourceAddress.getPortNumber());
362 // TODO Clean up the exception handling
363 @SuppressWarnings("checkstyle:IllegalCatch")
364 protected void releaseIpExtPortMapping(Uint32 segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
365 String internalIpPort = address.getIpAddress() + ":" + address.getPortNumber();
366 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
367 if (existingIpPort != null) {
368 // delete the entry from IpPortMap DS
370 removeFromIpPortMapDS(segmentId, internalIpPort, protocol);
371 // Finally release port from idmanager
372 Uint32 releasedId = NatUtil.releaseId(idManager, existingIpPort.getIpAddress(), internalIpPort);
373 if (releasedId == NatConstants.INVALID_ID) {
374 LOG.error("releaseIpExtPortMapping : Unable to release ID for key {}",
375 existingIpPort.getIpAddress());
377 } catch (Exception e) {
378 LOG.error("releaseIpExtPortMapping : failed, Removal of ipportmap {} for "
379 + "router {} failed", internalIpPort, segmentId, e);
382 LOG.error("releaseIpExtPortMapping : failed, segmentId {} and "
383 + "internalIpPort {} not found in IpPortMap DS", segmentId, internalIpPort);
386 //delete the entry of port for InternalIp from snatIntIpportMappingDS
387 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
388 final ReentrantLock lock = lockFor(segmentId, address.getIpAddress(), protocolType);
391 removeSnatIntIpPortDS(segmentId, address, protocolType);
392 } catch (Exception e) {
393 LOG.error("releaseSnatIpPortMapping : failed, Removal of snatipportmap {} for router {} failed",
394 address.getIpAddress(), segmentId, e);
401 * Removes the internal ip to external ip mapping if present.
403 * @param segmentId - Router ID
404 * @return true if successfully removed
406 // TODO Clean up the exception handling
407 @SuppressWarnings("checkstyle:IllegalCatch")
408 public boolean removeMapping(Uint32 segmentId) {
410 removeIpMappingForRouterID(segmentId);
411 removeIpPortMappingForRouterID(segmentId);
412 removeIntIpPortMappingForRouterID(segmentId);
413 } catch (Exception e) {
414 LOG.error("removeMapping : Removal of IPMapping for router {} failed", segmentId, e);
418 //TODO : This is when router is deleted then cleanup the entries in tables, ports etc - Delete scenarios
422 protected InstanceIdentifier<IpMap> getIpMapIdentifier(Uint32 segid, String internal) {
423 return InstanceIdentifier.builder(IntextIpMap.class)
424 .child(IpMapping.class, new IpMappingKey(segid))
425 .child(IpMap.class, new IpMapKey(internal)).build();
428 protected InstanceIdentifier<ExternalIpCounter> getExternalIpsIdentifier(Uint32 segmentId, String external) {
429 return InstanceIdentifier.builder(ExternalIpsCounter.class)
430 .child(ExternalCounters.class, new ExternalCountersKey(segmentId))
431 .child(ExternalIpCounter.class, new ExternalIpCounterKey(external)).build();
435 public static List<IpMap> getIpMapList(DataBroker broker, Uint32 routerId) {
436 InstanceIdentifier<IpMapping> id = getIpMapList(routerId);
437 return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
438 LogicalDatastoreType.OPERATIONAL, id).toJavaUtil().map(IpMapping::getIpMap).orElse(
439 Collections.emptyList());
442 protected static InstanceIdentifier<IpMapping> getIpMapList(Uint32 routerId) {
443 return InstanceIdentifier.builder(
444 IntextIpMap.class).child(IpMapping.class, new IpMappingKey(routerId)).build();
447 protected InstanceIdentifier<IpPortMap> getIpPortMapIdentifier(Uint32 segid, String internal,
448 NAPTEntryEvent.Protocol protocol) {
449 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
450 return InstanceIdentifier.builder(IntextIpPortMap.class)
451 .child(IpPortMapping.class, new IpPortMappingKey(segid))
452 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
453 .child(IpPortMap.class, new IpPortMapKey(internal)).build();
457 private SessionAddress checkIpPortMap(Uint32 segmentId, String internalIpPort,
458 NAPTEntryEvent.Protocol protocol) {
459 LOG.debug("checkIpPortMap : called with segmentId {} and internalIpPort {}",
460 segmentId, internalIpPort);
461 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
462 // check if ip-port-map node is there
463 InstanceIdentifierBuilder<IpPortMap> idBuilder =
464 InstanceIdentifier.builder(IntextIpPortMap.class)
465 .child(IpPortMapping.class, new IpPortMappingKey(segmentId))
466 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
467 .child(IpPortMap.class, new IpPortMapKey(internalIpPort));
468 InstanceIdentifier<IpPortMap> id = idBuilder.build();
469 Optional<IpPortMap> ipPortMapType =
470 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
471 if (ipPortMapType.isPresent()) {
472 LOG.debug("checkIpPortMap : {}", ipPortMapType.get());
473 SessionAddress externalIpPort = new SessionAddress(ipPortMapType.get().getIpPortExternal().getIpAddress(),
474 ipPortMapType.get().getIpPortExternal().getPortNum().toJava());
475 LOG.debug("checkIpPortMap : returning successfully externalIP {} and port {}",
476 externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
477 return externalIpPort;
479 // return null if not found
480 LOG.warn("checkIpPortMap : no-entry in checkIpPortMap, returning NULL [should be OK] for "
481 + "segmentId {} and internalIPPort {}", segmentId, internalIpPort);
486 protected String checkIpMap(Uint32 segmentId, String internalIp) {
487 LOG.debug("checkIpMap : called with segmentId {} and internalIp {}", segmentId, internalIp);
489 // check if ip-map node is there
490 InstanceIdentifierBuilder<IpMapping> idBuilder =
491 InstanceIdentifier.builder(IntextIpMap.class).child(IpMapping.class, new IpMappingKey(segmentId));
492 InstanceIdentifier<IpMapping> id = idBuilder.build();
493 Optional<IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
494 if (ipMapping.isPresent()) {
495 for (IpMap ipMap : ipMapping.get().nonnullIpMap()) {
496 if (Objects.equals(ipMap.getInternalIp(), internalIp)) {
497 LOG.debug("checkIpMap : IpMap : {}", ipMap);
498 externalIp = ipMap.getExternalIp();
499 LOG.debug("checkIpMap : successfully returning externalIp {}", externalIp);
501 } else if (ipMap.getInternalIp().contains("/")) { // subnet case
502 SubnetUtils subnetUtils = new SubnetUtils(ipMap.getInternalIp());
503 SubnetInfo subnetInfo = subnetUtils.getInfo();
504 if (subnetInfo.isInRange(internalIp)) {
505 LOG.debug("checkIpMap : internalIp {} found to be IpMap of internalIpSubnet {}",
506 internalIp, ipMap.getInternalIp());
507 externalIp = ipMap.getExternalIp();
508 LOG.debug("checkIpMap : checkIpMap successfully returning externalIp {}", externalIp);
514 // return null if not found
515 LOG.error("checkIpMap : failed, returning NULL for segmentId {} and internalIp {}",
516 segmentId, internalIp);
520 // TODO Clean up the exception handling
521 @SuppressWarnings("checkstyle:IllegalCatch")
522 protected void removeSnatIntIpPortDS(Uint32 segmentId, SessionAddress address, ProtocolTypes protocolType) {
523 LOG.trace("removeSnatIntIpPortDS : method called for IntIpport {} of router {} ",
525 List<Uint16> portList =
526 NatUtil.getInternalIpPortListInfo(dataBroker, segmentId, address.getIpAddress(), protocolType);
527 if (portList.isEmpty() || !portList.contains(Uint16.valueOf(address.getPortNumber()))) {
528 LOG.error("removeSnatIntIpPortDS : Internal IP {} for port {} entry not found in SnatIntIpPort DS",
529 address.getIpAddress(), address.getPortNumber());
532 LOG.trace("removeSnatIntIpPortDS : PortList {} retrieved for InternalIp {} of router {}",
533 portList, address.getIpAddress(), segmentId);
534 Integer port = address.getPortNumber();
535 portList.remove(Uint16.valueOf(port));
537 IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
538 IntIpProtoType intIpProtocolType =
539 builder.withKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
541 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
542 NatUtil.buildSnatIntIpPortIdentifier(segmentId, address.getIpAddress(), protocolType),
544 } catch (Exception ex) {
545 LOG.error("removeSnatIntIpPortDS : Failed to write into snat-internal-ip-port-info with exception", ex);
547 LOG.debug("removeSnatIntIpPortDS : Removing SnatIp {} Port {} of router {} from SNATIntIpport datastore",
548 address.getIpAddress(), address.getPortNumber(), segmentId);
551 protected void removeFromSnatIpPortDS(Uint32 segmentId, String internalIp) {
552 InstanceIdentifier<IpPort> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class)
553 .child(IntipPortMap.class, new IntipPortMapKey(segmentId))
554 .child(IpPort.class, new IpPortKey(internalIp)).build();
555 // remove from SnatIpPortDS
556 LOG.debug("removeFromSnatIpPortDS : Removing SnatIpPort from datastore : {}", intIp);
557 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
560 protected void removeFromIpPortMapDS(Uint32 segmentId, String internalIpPort, NAPTEntryEvent.Protocol protocol) {
561 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
562 removeFromIpPortMapDS(segmentId, internalIpPort, protocolType);
565 protected void removeFromIpPortMapDS(Uint32 segmentId, String internalIpPort, ProtocolTypes protocolType) {
566 InstanceIdentifierBuilder<IpPortMap> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
567 .child(IpPortMapping.class, new IpPortMappingKey(segmentId))
568 .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
569 .child(IpPortMap.class, new IpPortMapKey(internalIpPort));
570 InstanceIdentifier<IpPortMap> id = idBuilder.build();
571 // remove from ipportmap DS
572 LOG.debug("removeFromIpPortMapDS : Removing ipportmap from datastore : {}", id);
573 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
576 protected void removeFromIpMapDS(Uint32 segmentId, String internalIp) {
577 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
578 .child(IpMapping.class, new IpMappingKey(segmentId))
579 .child(IpMap.class, new IpMapKey(internalIp));
580 InstanceIdentifier<IpMap> id = idBuilder.build();
581 // Get externalIp and decrement the counter
582 String externalIp = null;
583 Optional<IpMap> ipMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
584 if (ipMap.isPresent()) {
585 externalIp = ipMap.get().getExternalIp();
586 LOG.debug("removeFromIpMapDS : externalIP is {}", externalIp);
588 LOG.warn("removeFromIpMapDS : ipMap not present for the internal IP {}", internalIp);
591 if (externalIp != null) {
592 updateCounter(segmentId, externalIp, false);
593 // remove from ipmap DS
594 LOG.debug("removeFromIpMapDS : Removing ipmap from datastore");
595 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
597 LOG.warn("removeFromIpMapDS : externalIp not present for the internal IP {}", internalIp);
601 protected void removeIntExtIpMapDS(Uint32 segmentId, String internalIp) {
602 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
603 .child(IpMapping.class, new IpMappingKey(segmentId))
604 .child(IpMap.class, new IpMapKey(internalIp));
605 InstanceIdentifier<IpMap> id = idBuilder.build();
607 LOG.debug("removeIntExtIpMapDS : Removing ipmap from datastore");
608 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
612 protected String getExternalIpAllocatedForSubnet(Uint32 segmentId, String internalIp) {
613 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
614 .child(IpMapping.class, new IpMappingKey(segmentId))
615 .child(IpMap.class, new IpMapKey(internalIp));
616 InstanceIdentifier<IpMap> id = idBuilder.build();
618 Optional<IpMap> ipMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
619 if (ipMap.isPresent()) {
620 return ipMap.get().getExternalIp();
625 private void removeIpMappingForRouterID(Uint32 segmentId) {
626 InstanceIdentifierBuilder<IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
627 .child(IpMapping.class, new IpMappingKey(segmentId));
628 InstanceIdentifier<IpMapping> id = idBuilder.build();
629 // Get all externalIps and decrement their counters before deleting the ipmap
630 Optional<IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
631 if (ipMapping.isPresent()) {
632 for (IpMap ipMap : ipMapping.get().nonnullIpMap()) {
633 String externalIp = ipMap.getExternalIp();
634 LOG.debug("removeIpMappingForRouterID : externalIP is {}", externalIp);
635 if (externalIp != null) {
636 updateCounter(segmentId, externalIp, false);
639 // remove from ipmap DS
640 LOG.debug("removeIpMappingForRouterID : Removing Ipmap for router {} from datastore", segmentId);
641 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
645 void removeIpPortMappingForRouterID(Uint32 segmentId) {
646 InstanceIdentifier<IpPortMapping> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
647 .child(IpPortMapping.class, new IpPortMappingKey(segmentId)).build();
648 Optional<IpPortMapping> ipPortMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
650 if (ipPortMapping.isPresent()) {
651 // remove from IntExtIpPortmap DS
652 LOG.debug("removeIpPortMappingForRouterID : Removing IntExtIpPort map for router {} from datastore",
654 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, idBuilder);
658 void removeIntIpPortMappingForRouterID(Uint32 segmentId) {
659 InstanceIdentifier<IntipPortMap> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class)
660 .child(IntipPortMap.class, new IntipPortMapKey(segmentId)).build();
661 Optional<IntipPortMap> intIpPortMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
662 if (intIpPortMap.isPresent()) {
663 // remove from SnatIntIpPortmap DS
664 LOG.debug("removeIntIpPortMappingForRouterID : Removing SnatIntIpPort from datastore : {}", intIp);
665 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
669 void removePortFromPool(String internalIpPort, String externalIp) {
670 if (NatUtil.releaseId(idManager, externalIp, internalIpPort) == NatConstants.INVALID_ID) {
671 LOG.error("Unable to release id {} from Pool {}", internalIpPort, externalIp);
675 protected void initialiseExternalCounter(Routers routers, Uint32 routerId) {
676 LOG.debug("initialiseExternalCounter : Initialise External IPs counter");
678 //update the new counter value for this externalIp
679 for (ExternalIps externalIp : routers.nonnullExternalIps()) {
680 String[] ipSplit = externalIp.getIpAddress().split("/");
681 String extIp = ipSplit[0];
682 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
683 if (ipSplit.length == 2) {
684 extPrefix = ipSplit[1];
686 extIp = extIp + "/" + extPrefix;
687 initialiseNewExternalIpCounter(routerId, extIp);
691 protected void initialiseNewExternalIpCounter(Uint32 routerId, String externalIp) {
692 ExternalIpCounter externalIpCounterData = new ExternalIpCounterBuilder()
693 .withKey(new ExternalIpCounterKey(externalIp)).setExternalIp(externalIp).setCounter((short) 0).build();
694 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
695 getExternalIpsIdentifier(routerId, externalIp), externalIpCounterData);
698 protected void removeExternalCounter(Uint32 routerId) {
699 // Remove from external-counters model
700 InstanceIdentifier<ExternalCounters> id = InstanceIdentifier.builder(ExternalIpsCounter.class)
701 .child(ExternalCounters.class, new ExternalCountersKey(routerId)).build();
702 LOG.debug("removeExternalCounter : Removing ExternalCounterd from datastore");
703 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
706 protected void removeExternalIpCounter(Uint32 routerId, String externalIp) {
707 // Remove from external-counters model
708 InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class)
709 .child(ExternalCounters.class, new ExternalCountersKey(routerId))
710 .child(ExternalIpCounter.class, new ExternalIpCounterKey(externalIp)).build();
711 LOG.debug("removeExternalIpCounter : Removing ExternalIpsCounter from datastore");
712 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
715 private static ReentrantLock lockFor(final Uint32 segmentId, String ipAddress, final ProtocolTypes protocolType) {
716 // FIXME: use an Identifier class instead?
717 String lockName = new StringBuilder()
719 .append(NatConstants.COLON_SEPARATOR)
721 .append(NatConstants.COLON_SEPARATOR)
722 .append(protocolType.getName()).toString();
724 return JvmGlobalLocks.getLockForString(lockName);