2 * Copyright (c) 2016 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 java.util.ArrayList;
15 import java.util.Arrays;
16 import java.util.List;
17 import java.util.concurrent.Future;
18 import java.util.concurrent.ExecutionException;
20 import com.google.common.collect.Lists;
21 import org.apache.commons.net.util.SubnetUtils;
22 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.genius.mdsalutil.MDSALUtil;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpMap;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.SnatintIpPortMap;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCountersKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounterKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMappingKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolTypeKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapKey;
58 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;
59 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;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMap;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMapKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPortKey;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeKey;
67 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
68 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
69 import org.opendaylight.yangtools.yang.common.RpcResult;
70 import org.slf4j.Logger;
71 import org.slf4j.LoggerFactory;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounterBuilder;
74 import com.google.common.base.Optional;
75 import com.google.common.util.concurrent.UncheckedExecutionException;
77 public class NaptManager {
78 private static final Logger LOG = LoggerFactory.getLogger(NaptManager.class);
79 private final DataBroker dataBroker;
80 private final IdManagerService idManager;
81 private static final long LOW_PORT = 49152L;
82 private static final long HIGH_PORT = 65535L;
83 private static boolean EXTSUBNET_FLAG = false;
84 private static boolean NEXT_EXTIP_FLAG = false;
86 public NaptManager(final DataBroker dataBroker, final IdManagerService idManager) {
87 this.dataBroker = dataBroker;
88 this.idManager = idManager;
91 protected void createNaptPortPool(String PoolName) {
92 LOG.debug("NAPT Service : createPortPool requested for : {}", PoolName);
93 CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
94 .setPoolName(PoolName)
99 Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
100 if ((result != null) && (result.get().isSuccessful())) {
101 LOG.debug("NAPT Service : Created PortPool");
103 LOG.error("NAPT Service : Unable to create PortPool");
105 } catch (InterruptedException | ExecutionException e) {
106 LOG.error("Failed to create PortPool for NAPT Service",e);
110 void removeNaptPortPool(String poolName) {
111 DeleteIdPoolInput deleteIdPoolInput = new DeleteIdPoolInputBuilder().setPoolName(poolName).build();
112 LOG.debug("NAPT Service : Remove Napt port pool requested for : {}", poolName);
114 Future<RpcResult<Void>> result = idManager.deleteIdPool(deleteIdPoolInput);
115 if ((result != null) && (result.get().isSuccessful())) {
116 LOG.debug("NAPT Service : Deleted PortPool {}", poolName);
118 LOG.error("NAPT Service : Unable to delete PortPool {}", poolName);
120 } catch (InterruptedException | ExecutionException e) {
121 LOG.error("Failed to delete PortPool {} for NAPT Service", poolName, e);
125 // 1. napt service functions
127 * this method is used to inform this service of what external IP address to be used
128 * as mapping when requested one for the internal IP address given in the input
129 * @param segmentId – segmentation in which the mapping to be used. Eg; routerid
130 * @param internal subnet prefix or ip address
131 * @param external subnet prefix or ip address
134 public void registerMapping(long segmentId, IPAddress internal, IPAddress external) {
136 LOG.debug("NAPT Service : registerMapping called with segmentid {}, internalIp {}, prefix {}, externalIp {} and prefix {} ", segmentId, internal.getIpAddress(),
137 internal.getPrefixLength(), external.getIpAddress(), external.getPrefixLength());
138 // Create Pool per ExternalIp and not for all IPs in the subnet. Create new Pools during getExternalAddressMapping if exhausted.
139 String externalIpPool;
140 if (external.getPrefixLength() !=0 && external.getPrefixLength() != NatConstants.DEFAULT_PREFIX) { // subnet case
141 String externalSubnet = new StringBuilder(64).append(external.getIpAddress()).append("/").append(external.getPrefixLength()).toString();
142 LOG.debug("NAPT Service : externalSubnet is : {}", externalSubnet);
143 SubnetUtils subnetUtils = new SubnetUtils(externalSubnet);
144 SubnetInfo subnetInfo = subnetUtils.getInfo();
145 externalIpPool = subnetInfo.getLowAddress();
147 externalIpPool = external.getIpAddress();
149 createNaptPortPool(externalIpPool);
151 // Store the ip to ip map in Operational DS
152 String internalIp = internal.getIpAddress();
153 if(internal.getPrefixLength() != 0) {
154 internalIp = new StringBuilder(64).append(internal.getIpAddress()).append("/").append(internal.getPrefixLength()).toString();
156 String externalIp = external.getIpAddress();
157 if(external.getPrefixLength() != 0) {
158 externalIp = new StringBuilder(64).append(external.getIpAddress()).append("/").append(external.getPrefixLength()).toString();
160 updateCounter(segmentId, externalIp, true);
161 //update the actual ip-map
162 IpMap ipm = new IpMapBuilder().setKey(new IpMapKey(internalIp)).setInternalIp(internalIp).setExternalIp(externalIp).build();
163 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, getIpMapIdentifier(segmentId, internalIp), ipm);
164 LOG.debug("NAPT Service : registerMapping exit after updating DS with internalIP {}, externalIP {}", internalIp, externalIp);
167 public void updateCounter(long segmentId, String externalIp, boolean isAdd){
169 InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).child(ExternalCounters.class, new ExternalCountersKey(segmentId)).child(ExternalIpCounter.class, new ExternalIpCounterKey(externalIp)).build();
170 Optional <ExternalIpCounter> externalIpCounter = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
171 if (externalIpCounter.isPresent()) {
172 counter = externalIpCounter.get().getCounter();
175 LOG.debug("NAT Service : externalIp and counter after increment are {} and {}", externalIp, counter);
180 LOG.debug("NAT Service : externalIp and counter after decrement are {} and {}", externalIp, counter);
187 //update the new counter value for this externalIp
188 ExternalIpCounter externalIpCounterData = new ExternalIpCounterBuilder().setKey(new ExternalIpCounterKey(externalIp)).setExternalIp(externalIp).setCounter(counter).build();
189 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, getExternalIpsIdentifier(segmentId, externalIp), externalIpCounterData);
194 * method to get external ip/port mapping when provided with internal ip/port pair
195 * If already a mapping exist for the given input, then the existing mapping is returned
196 * instead of overwriting with new ip/port pair.
198 * @param sourceAddress - internal ip address/port pair
199 * @return external ip address/port
201 public SessionAddress getExternalAddressMapping(long segmentId, SessionAddress sourceAddress, NAPTEntryEvent.Protocol protocol) {
202 LOG.debug("NAPT Service : getExternalAddressMapping called with segmentId {}, internalIp {} and port {}",
203 segmentId, sourceAddress.getIpAddress(), sourceAddress.getPortNumber());
205 1. Get Internal IP, Port in IP:Port format
206 2. Inside DB with routerId get the list of entries and check if it matches with existing IP:Port
207 3. If True return SessionAddress of ExternalIp and Port
208 4. Else check ip Map and Form the ExternalIp and Port and update DB and then return ExternalIp and Port
211 //SessionAddress externalIpPort = new SessionAddress();
212 String internalIpPort = new StringBuilder(64).append(sourceAddress.getIpAddress()).append(":").append(sourceAddress.getPortNumber()).toString();
214 // First check existing Port Map.
215 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
216 if(existingIpPort != null) {
217 // populate externalIpPort from IpPortMap and return
218 LOG.debug("NAPT Service : getExternalAddressMapping successfully returning existingIpPort as {} and {}", existingIpPort.getIpAddress(), existingIpPort.getPortNumber());
219 return existingIpPort;
221 // Now check in ip-map
222 String externalIp = checkIpMap(segmentId, sourceAddress.getIpAddress());
223 if(externalIp == null) {
224 LOG.error("NAPT Service : getExternalAddressMapping, Unexpected error, internal to external ip map does not exist");
227 /* Logic assuming internalIp is always ip and not subnet
228 * case 1: externalIp is ip
229 * a) goto externalIp pool and getPort and return
230 * b) else return error
231 * case 2: externalIp is subnet
232 * a) Take first externalIp and goto that Pool and getPort
234 * else Take second externalIp and create that Pool and getPort
237 * Continue same with third externalIp till we exhaust subnet
238 * b) Nothing worked return error
240 SubnetUtils externalIpSubnet;
241 List<String> allIps = new ArrayList<>();
242 String subnetPrefix = "/" + String.valueOf(NatConstants.DEFAULT_PREFIX);
243 if( !externalIp.contains(subnetPrefix) ) {
244 EXTSUBNET_FLAG = true;
245 externalIpSubnet = new SubnetUtils(externalIp);
246 allIps = Arrays.asList(externalIpSubnet.getInfo().getAllAddresses());
247 LOG.debug("NAPT Service : total count of externalIps available {}", externalIpSubnet.getInfo().getAddressCount());
249 LOG.debug("NAPT Service : getExternalAddress single ip case");
250 if(externalIp.contains(subnetPrefix)) {
251 String[] externalIpSplit = externalIp.split("/");
252 String extIp = externalIpSplit[0];
253 externalIp = extIp; //remove /32 what we got from checkIpMap
255 allIps.add(externalIp);
258 for(String extIp : allIps) {
259 LOG.info("NAPT Service : Looping externalIPs with externalIP now as {}", extIp);
260 if(NEXT_EXTIP_FLAG) {
261 createNaptPortPool(extIp);
262 LOG.debug("NAPT Service : Created Pool for next Ext IP {}", extIp);
264 AllocateIdInput getIdInput = new AllocateIdInputBuilder()
265 .setPoolName(extIp).setIdKey(internalIpPort)
268 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
269 RpcResult<AllocateIdOutput> rpcResult;
270 if ((result != null) && (result.get().isSuccessful())) {
271 LOG.debug("NAPT Service : Got id from idManager");
272 rpcResult = result.get();
274 LOG.error("NAPT Service : getExternalAddressMapping, idManager could not allocate id retry if subnet");
275 if(!EXTSUBNET_FLAG) {
276 LOG.error("NAPT Service : getExternalAddressMapping returning null for single IP case, may be ports exhausted");
279 LOG.debug("NAPT Service : Could be ports exhausted case, try with another externalIP if possible");
280 NEXT_EXTIP_FLAG = true;
283 int extPort= rpcResult.getResult().getIdValue().intValue();
284 SessionAddress externalIpPort = new SessionAddress(extIp, extPort);
285 // Write to ip-port-map before returning
286 IpPortExternalBuilder ipExt = new IpPortExternalBuilder();
287 IpPortExternal ipPortExt = ipExt.setIpAddress(extIp).setPortNum(extPort).build();
288 IpPortMap ipm = new IpPortMapBuilder().setKey(new IpPortMapKey(internalIpPort))
289 .setIpPortInternal(internalIpPort).setIpPortExternal(ipPortExt).build();
290 LOG.debug("NAPT Service : getExternalAddressMapping writing into ip-port-map with externalIP {} and port {}",
291 ipPortExt.getIpAddress(), ipPortExt.getPortNum());
293 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
294 getIpPortMapIdentifier(segmentId, internalIpPort, protocol), ipm);
295 } catch (UncheckedExecutionException uee) {
296 LOG.error("NAPT Service : Failed to write into ip-port-map with exception {}", uee.getMessage() );
299 // Write to snat-internal-ip-port-info
300 String internalIpAddress = sourceAddress.getIpAddress();
301 int ipPort = sourceAddress.getPortNumber();
302 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
303 List<Integer> portList = NatUtil.getInternalIpPortListInfo(dataBroker,segmentId,internalIpAddress,protocolType);
304 if (portList == null) {
305 portList = Lists.newArrayList();
307 portList.add(ipPort);
309 IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
310 IntIpProtoType intIpProtocolType = builder.setKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
312 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
313 NatUtil.buildSnatIntIpPortIdentifier(segmentId, internalIpAddress, protocolType), intIpProtocolType);
314 } catch (Exception ex) {
315 LOG.error("NAPT Service : Failed to write into snat-internal-ip-port-info with exception {}", ex.getMessage() );
318 LOG.debug("NAPT Service : getExternalAddressMapping successfully returning externalIP {} and port {}",
319 externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
320 return externalIpPort;
321 } catch(InterruptedException | ExecutionException e) {
322 LOG.error("NAPT Service : getExternalAddressMapping, Exception caught {}",e);
326 }// end of else ipmap present
327 }// end of else check ipmap
328 LOG.error("NAPT Service: getExternalAddressMapping returning null, nothing worked or externalIPs exhausted");
334 * release the existing mapping of internal ip/port to external ip/port pair
335 * if no mapping exist for given internal ip/port, it returns false
338 * @return true if mapping exist and the mapping is removed successfully
341 public boolean releaseAddressMapping(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
343 LOG.debug("NAPT Service : releaseAddressMapping called with segmentId {}, internalIP {}, port {}", segmentId, address.getIpAddress(), address.getPortNumber());
344 // delete entry from IpPort Map and IP Map if exists
345 String internalIpPort = new StringBuilder(64).append(address.getIpAddress()).append(":").append(address.getPortNumber()).toString();
346 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
347 if(existingIpPort != null) {
348 // delete the entry from IpPortMap DS
350 removeFromIpPortMapDS(segmentId, internalIpPort , protocol);
351 } catch (Exception e){
352 LOG.error("NAPT Service : releaseAddressMapping failed, Removal of ipportmap {} for router {} failed {}" , internalIpPort, segmentId, e);
356 LOG.error("NAPT Service : releaseAddressMapping failed, segmentId {} and internalIpPort {} not found in IpPortMap DS", segmentId, internalIpPort);
359 String existingIp = checkIpMap(segmentId, address.getIpAddress());
360 if(existingIp != null) {
361 // delete the entry from IpMap DS
363 removeFromIpMapDS(segmentId, address.getIpAddress());
364 } catch (Exception e){
365 LOG.error("NAPT Service : Removal of ipmap {} for router {} failed {}" , address.getIpAddress(), segmentId, e);
368 //delete the entry from snatIntIpportinfo
370 removeFromSnatIpPortDS(segmentId, address.getIpAddress());
371 } catch (Exception e){
372 LOG.error("NAPT Service : releaseAddressMapping failed, Removal of snatipportmap {} for router {} failed {}" , address.getIpAddress(), segmentId, e);
376 LOG.error("NAPT Service : releaseAddressMapping failed, segmentId {} and internalIpPort {} not found in IpMap DS", segmentId, internalIpPort);
379 // Finally release port from idmanager
380 removePortFromPool(internalIpPort, existingIpPort.getIpAddress());
382 LOG.debug("NAPT Service : Exit of releaseAddressMapping successfully for segmentId {} and internalIpPort {}", segmentId, internalIpPort);
387 protected void releaseIpExtPortMapping(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
388 String internalIpPort = address.getIpAddress() + ":" + address.getPortNumber();
389 SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
390 if(existingIpPort != null) {
391 // delete the entry from IpPortMap DS
393 removeFromIpPortMapDS(segmentId, internalIpPort , protocol);
394 // Finally release port from idmanager
395 removePortFromPool(internalIpPort, existingIpPort.getIpAddress());
396 } catch (Exception e){
397 LOG.error("NAPT Service : releaseAddressMapping failed, Removal of ipportmap {} for router {} failed {}" ,
398 internalIpPort, segmentId, e);
401 LOG.error("NAPT Service : releaseIpExtPortMapping failed, segmentId {} and internalIpPort {} not found in IpPortMap DS", segmentId, internalIpPort);
404 //delete the entry of port for InternalIp from snatIntIpportMappingDS
406 removeSnatIntIpPortDS(segmentId,address, protocol);
407 } catch (Exception e){
408 LOG.error("NAPT Service : releaseSnatIpPortMapping failed, Removal of snatipportmap {} for router {} failed {}" ,
409 address.getIpAddress(), segmentId, e);
414 * removes the internal ip to external ip mapping if present
416 * @return true if successfully removed
418 public boolean removeMapping(long segmentId) {
420 removeIpMappingForRouterID(segmentId);
421 removeIpPortMappingForRouterID(segmentId);
422 removeIntIpPortMappingForRouterID(segmentId);
423 } catch (Exception e){
424 LOG.error("NAPT Service : Removal of IPMapping for router {} failed {}" , segmentId, e);
428 //TODO : This is when router is deleted then cleanup the entries in tables, ports etc - Delete scenarios
432 // 2. Utility functions
433 protected InstanceIdentifier<IpMap> getIpMapIdentifier(long segid, String internal) {
434 InstanceIdentifier<IpMap> id = InstanceIdentifier.builder(
435 IntextIpMap.class).child(IpMapping.class, new IpMappingKey(segid)).child(IpMap.class, new IpMapKey(internal)).build();
439 protected InstanceIdentifier<ExternalIpCounter> getExternalIpsIdentifier(long segmentId, String external) {
440 InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).child(ExternalCounters.class, new ExternalCountersKey(segmentId))
441 .child(ExternalIpCounter.class, new ExternalIpCounterKey(external)).build();
445 public static List<IpMap> getIpMapList(DataBroker broker, Long routerId) {
446 InstanceIdentifier<IpMapping> id = getIpMapList(routerId);
447 Optional<IpMapping> ipMappingListData = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
448 if (ipMappingListData.isPresent()) {
449 IpMapping ipMapping = ipMappingListData.get();
450 return ipMapping.getIpMap();
455 protected static InstanceIdentifier<IpMapping> getIpMapList(long routerId) {
456 InstanceIdentifier<IpMapping> id = InstanceIdentifier.builder(
457 IntextIpMap.class).child(IpMapping.class, new IpMappingKey(routerId)).build();
461 protected InstanceIdentifier<IpPortMap> getIpPortMapIdentifier(long segid, String internal, NAPTEntryEvent.Protocol protocol) {
462 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
463 InstanceIdentifier<IpPortMap> id = InstanceIdentifier.builder(
464 IntextIpPortMap.class).child(IpPortMapping.class, new IpPortMappingKey(segid)).child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType)).
465 child(IpPortMap.class, new IpPortMapKey(internal)).build();
469 protected SessionAddress checkIpPortMap(long segmentId, String internalIpPort, NAPTEntryEvent.Protocol protocol) {
471 LOG.debug("NAPT Service : checkIpPortMap called with segmentId {} and internalIpPort {}", segmentId, internalIpPort);
472 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
473 // check if ip-port-map node is there
474 InstanceIdentifierBuilder<IntextIpProtocolType> idBuilder =
475 InstanceIdentifier.builder(IntextIpPortMap.class).child(IpPortMapping.class, new IpPortMappingKey(segmentId)).child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType));
476 InstanceIdentifier<IntextIpProtocolType> id = idBuilder.build();
477 Optional<IntextIpProtocolType> intextIpProtocolType = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
478 if (intextIpProtocolType.isPresent()) {
479 List<IpPortMap> ipPortMaps = intextIpProtocolType.get().getIpPortMap();
480 for (IpPortMap ipPortMap : ipPortMaps) {
481 if (ipPortMap.getIpPortInternal().equals(internalIpPort)) {
482 LOG.debug("NAPT Service : IpPortMap : {}", ipPortMap);
483 SessionAddress externalIpPort = new SessionAddress(ipPortMap.getIpPortExternal().getIpAddress(),
484 ipPortMap.getIpPortExternal().getPortNum());
485 LOG.debug("NAPT Service : checkIpPortMap returning successfully externalIP {} and port {}",
486 externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
487 return externalIpPort;
491 // return null if not found
492 LOG.error("NAPT Service : no-entry in checkIpPortMap, returning NULL [should be OK] for segmentId {} and internalIPPort {}", segmentId, internalIpPort);
496 protected String checkIpMap(long segmentId, String internalIp) {
498 LOG.debug("NAPT Service : checkIpMap called with segmentId {} and internalIp {}", segmentId, internalIp);
500 // check if ip-map node is there
501 InstanceIdentifierBuilder<IpMapping> idBuilder =
502 InstanceIdentifier.builder(IntextIpMap.class).child(IpMapping.class, new IpMappingKey(segmentId));
503 InstanceIdentifier<IpMapping> id = idBuilder.build();
504 Optional<IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
505 if (ipMapping.isPresent()) {
506 List<IpMap> ipMaps = ipMapping.get().getIpMap();
507 for (IpMap ipMap : ipMaps) {
508 if (ipMap.getInternalIp().equals(internalIp)) {
509 LOG.debug("NAPT Service : IpMap : {}", ipMap);
510 externalIp = ipMap.getExternalIp().toString();
511 LOG.debug("NAPT Service : checkIpMap successfully returning externalIp {}", externalIp );
513 } else if (ipMap.getInternalIp().contains("/")) { // subnet case
514 SubnetUtils subnetUtils = new SubnetUtils(ipMap.getInternalIp());
515 SubnetInfo subnetInfo = subnetUtils.getInfo();
516 if (subnetInfo.isInRange(internalIp)) {
517 LOG.debug("NAPT Service : internalIp {} found to be IpMap of internalIpSubnet {}", internalIp, ipMap.getInternalIp());
518 externalIp = ipMap.getExternalIp().toString();
519 LOG.debug("NAPT Service : checkIpMap successfully returning externalIp {}", externalIp );
525 // return null if not found
526 LOG.error("NAPT Service : checkIpMap failed, returning NULL for segmentId {} and internalIp {}", segmentId, internalIp);
530 protected void removeSnatIntIpPortDS(long segmentId, SessionAddress address,NAPTEntryEvent.Protocol protocol) {
531 LOG.trace("NAPT Service : removeSnatIntIpPortDS method called for IntIpport {} of router {} ",address,segmentId);
532 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
533 List<Integer> portList = NatUtil.getInternalIpPortListInfo(dataBroker,segmentId,address.getIpAddress(),protocolType);
534 if (portList == null || portList.isEmpty() || !portList.contains(address.getPortNumber())) {
535 LOG.debug("Internal IP {} for port {} entry not found in SnatIntIpPort DS",address.getIpAddress(),address.getPortNumber());
538 LOG.trace("NAPT Service : PortList {} retrieved for InternalIp {} of router {}",portList,address.getIpAddress(),segmentId);
539 Integer port = address.getPortNumber();
540 portList.remove(port);
542 IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
543 IntIpProtoType intIpProtocolType = builder.setKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
545 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, NatUtil.buildSnatIntIpPortIdentifier(segmentId, address.getIpAddress(), protocolType), intIpProtocolType);
546 } catch (Exception ex) {
547 LOG.error("NAPT Service : Failed to write into snat-internal-ip-port-info with exception {}", ex.getMessage() );
549 LOG.debug("NAPT Service : Removing SnatIp {} Port {} of router {} from SNATIntIpport datastore : {}"
550 ,address.getIpAddress(),address.getPortNumber(),segmentId);
553 protected void removeFromSnatIpPortDS(long segmentId, String internalIp) {
554 InstanceIdentifier<IpPort> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class).child
555 (IntipPortMap.class, new IntipPortMapKey(segmentId)).child(IpPort.class, new IpPortKey(internalIp)).build();
556 // remove from SnatIpPortDS
557 LOG.debug("NAPT Service : Removing SnatIpPort from datastore : {}", intIp);
558 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
562 protected void removeFromIpPortMapDS(long segmentId, String internalIpPort, NAPTEntryEvent.Protocol protocol) {
563 ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
564 removeFromIpPortMapDS(segmentId, internalIpPort, protocolType);
567 protected void removeFromIpPortMapDS(long segmentId, String internalIpPort, ProtocolTypes protocolType) {
568 InstanceIdentifierBuilder<IpPortMap> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
569 .child(IpPortMapping.class, new IpPortMappingKey(segmentId)).child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
570 .child(IpPortMap.class, new IpPortMapKey(internalIpPort));
571 InstanceIdentifier<IpPortMap> id = idBuilder.build();
572 // remove from ipportmap DS
573 LOG.debug("NAPT Service : Removing ipportmap from datastore : {}", id);
574 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
577 protected void removeFromIpMapDS(long segmentId, String internalIp) {
578 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
579 .child(IpMapping.class, new IpMappingKey(segmentId))
580 .child(IpMap.class, new IpMapKey(internalIp));
581 InstanceIdentifier<IpMap> id = idBuilder.build();
582 // Get externalIp and decrement the counter
583 String externalIp = null;
584 Optional<IpMap> ipMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
585 if (ipMap.isPresent()) {
586 externalIp = ipMap.get().getExternalIp();
587 LOG.debug("NAT Service : externalIP is {}", externalIp);
589 LOG.warn("NAT Service : ipMap not present for the internal IP {}", internalIp);
592 if(externalIp!=null) {
593 updateCounter(segmentId, externalIp, false);
594 // remove from ipmap DS
595 LOG.debug("NAPT Service : Removing ipmap from datastore");
596 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
598 LOG.warn("NAT Service : externalIp not present for the internal IP {}", internalIp);
602 protected void removeIntExtIpMapDS(long segmentId, String internalIp) {
603 InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
604 .child(IpMapping.class, new IpMappingKey(segmentId))
605 .child(IpMap.class, new IpMapKey(internalIp));
606 InstanceIdentifier<IpMap> id = idBuilder.build();
608 LOG.debug("NAPT Service : Removing ipmap from datastore");
609 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
612 protected String getExternalIpAllocatedForSubnet(long 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(long 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 String externalIp = null;
631 Optional<IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
632 if (ipMapping.isPresent()) {
633 List<IpMap> ipMaps = ipMapping.get().getIpMap();
634 for (IpMap ipMap : ipMaps) {
635 externalIp = ipMap.getExternalIp();
636 LOG.debug("NAT Service : externalIP is {}", externalIp);
637 if(externalIp!=null) {
638 updateCounter(segmentId, externalIp, false);
642 // remove from ipmap DS
643 LOG.debug("NAPT Service : Removing Ipmap for router {} from datastore",segmentId);
644 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
647 void removeIpPortMappingForRouterID(long segmentId) {
648 InstanceIdentifier<IpPortMapping> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
649 .child(IpPortMapping.class, new IpPortMappingKey(segmentId)).build();
650 // remove from IntExtIpPortmap DS
651 LOG.debug("NAPT Service : Removing IntExtIpPort map for router {} from datastore",segmentId);
652 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, idBuilder);
655 void removeIntIpPortMappingForRouterID(long segmentId) {
656 InstanceIdentifier<IntipPortMap> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class).child
657 (IntipPortMap.class, new IntipPortMapKey(segmentId)).build();
658 // remove from SnatIntIpPortmap DS
659 LOG.debug("NAPT Service : Removing SnatIntIpPort from datastore : {}", intIp);
660 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp);
663 void removePortFromPool(String internalIpPort, String externalIp) {
664 LOG.debug("NAPT Service : removePortFromPool method called");
665 ReleaseIdInput idInput = new ReleaseIdInputBuilder().
666 setPoolName(externalIp)
667 .setIdKey(internalIpPort).build();
669 Future<RpcResult<Void>> result = idManager.releaseId(idInput);
670 RpcResult<Void> rpcResult = result.get();
671 if(!rpcResult.isSuccessful()) {
672 LOG.error("NAPT Service : idmanager failed to remove port from pool {}", rpcResult.getErrors());
674 LOG.debug("NAPT Service : Removed port from pool for InternalIpPort {} with externalIp {}",internalIpPort,externalIp);
675 } catch (InterruptedException | ExecutionException e) {
676 LOG.error("NAPT Service : idmanager failed with Exception {} when removing entry in pool with key {}, ", e, internalIpPort);
680 protected void initialiseExternalCounter(Routers routers, long routerId){
681 LOG.debug("NAPT Service : Initialise External IPs counter");
682 List<String> externalIps = routers.getExternalIps();
684 //update the new counter value for this externalIp
685 for(String externalIp : externalIps) {
686 String[] IpSplit = externalIp.split("/");
687 String extIp = IpSplit[0];
688 String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
689 if(IpSplit.length==2) {
690 extPrefix = IpSplit[1];
692 extIp = extIp + "/" + extPrefix;
693 initialiseNewExternalIpCounter(routerId, extIp);
697 protected void initialiseNewExternalIpCounter(long routerId, String ExternalIp){
698 ExternalIpCounter externalIpCounterData = new ExternalIpCounterBuilder().setKey(new ExternalIpCounterKey(ExternalIp)).
699 setExternalIp(ExternalIp).setCounter((short) 0).build();
700 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, getExternalIpsIdentifier(routerId, ExternalIp), externalIpCounterData);
703 protected void removeExternalCounter(long routerId){
704 // Remove from external-counters model
705 InstanceIdentifier<ExternalCounters> id = InstanceIdentifier.builder(ExternalIpsCounter.class).child(ExternalCounters.class, new ExternalCountersKey(routerId)).build();
706 LOG.debug("NAPT Service : Removing ExternalCounterd from datastore");
707 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
710 protected void removeExternalIpCounter(long routerId, String externalIp){
711 // Remove from external-counters model
712 InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).child(ExternalCounters.class,
713 new ExternalCountersKey(routerId)).child(ExternalIpCounter.class, new ExternalIpCounterKey(externalIp)).build();
714 LOG.debug("NAPT Service : Removing ExternalIpsCounter from datastore");
715 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);