Merge "LLDP monitor interval update fixes"
[vpnservice.git] / natservice / natservice-impl / src / main / java / org / opendaylight / vpnservice / natservice / internal / NaptManager.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8
9 /*
10  * Created eyugsar 2016/12/1
11  */
12
13 package org.opendaylight.vpnservice.natservice.internal;
14
15
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.List;
19 import java.util.concurrent.Future;
20 import java.util.concurrent.ExecutionException;
21
22 import com.google.common.collect.Lists;
23 import org.apache.commons.net.util.SubnetUtils;
24 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.IntextIpMap;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.IntextIpPortMap;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ProtocolTypes;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.SnatintIpPortMap;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.Ports;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.PortsBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMappingKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMapping;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolTypeKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternalBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.id.name.RouterIds;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.IntipPortMap;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.IntipPortMapKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPortKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeKey;
64 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
65 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
66 import org.opendaylight.yangtools.yang.common.RpcResult;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
69
70 import com.google.common.base.Optional;
71 import com.google.common.util.concurrent.UncheckedExecutionException;
72
73 public class NaptManager  {
74     private static final Logger LOG = LoggerFactory.getLogger(NaptManager.class);
75     private final DataBroker broker;
76     private IdManagerService idManager;
77     private static final long LOW_PORT = 49152L;
78     private static final long HIGH_PORT = 65535L;
79     private static boolean EXTSUBNET_FLAG = false;
80     private static boolean NEXT_EXTIP_FLAG = false;
81
82     public NaptManager(final DataBroker db) {
83         this.broker = db;
84     }
85
86     public void setIdManager(IdManagerService idManager) {
87         this.idManager = idManager;
88     }
89
90     protected void createNaptPortPool(String PoolName) {
91          LOG.debug("NAPT Service : createPortPool requested for : {}", PoolName);
92          CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
93              .setPoolName(PoolName)
94              .setLow(LOW_PORT)
95              .setHigh(HIGH_PORT)
96              .build();
97          try {
98              Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
99              if ((result != null) && (result.get().isSuccessful())) {
100                  LOG.debug("NAPT Service : Created PortPool");
101              } else {
102                  LOG.error("NAPT Service : Unable to create PortPool");
103              }
104          } catch (InterruptedException | ExecutionException e) {
105              LOG.error("Failed to create PortPool for NAPT Service",e);
106          }
107     }
108
109      // 1. napt service functions
110      /**
111       * this method is used to inform this service of what external IP address to be used
112       * as mapping when requested one for the internal IP address given in the input
113       * @param segmentId – segmentation in which the mapping to be used. Eg; routerid
114       * @param internal subnet prefix or ip address
115       * @param external subnet prefix or ip address
116       */
117
118       public void registerMapping(long segmentId, IPAddress internal, IPAddress external) {
119
120           LOG.debug("NAPT Service : registerMapping called with segmentid {}, internalIp {}, prefix {}, externalIp {} and prefix {} ", segmentId, internal.getIpAddress(),
121                 internal.getPrefixLength(), external.getIpAddress(), external.getPrefixLength());
122         // Create Pool per ExternalIp and not for all IPs in the subnet. Create new Pools during getExternalAddressMapping if exhausted.
123         String externalIpPool;
124         if (external.getPrefixLength() !=0 && external.getPrefixLength() != NatConstants.DEFAULT_PREFIX) {  // subnet case
125             String externalSubnet = new StringBuilder(64).append(external.getIpAddress()).append("/").append(external.getPrefixLength()).toString();
126             LOG.debug("NAPT Service : externalSubnet is : {}", externalSubnet);
127             SubnetUtils subnetUtils = new SubnetUtils(externalSubnet);
128             SubnetInfo subnetInfo = subnetUtils.getInfo();
129             externalIpPool = subnetInfo.getLowAddress();
130         } else {  // ip case
131             externalIpPool = external.getIpAddress();
132         }
133         createNaptPortPool(externalIpPool);
134
135         // Store the ip to ip map in Operational DS
136         String internalIp = internal.getIpAddress();
137         if(internal.getPrefixLength() != 0) {
138             internalIp =  new StringBuilder(64).append(internal.getIpAddress()).append("/").append(internal.getPrefixLength()).toString();
139         }
140         String externalIp = external.getIpAddress();
141         if(external.getPrefixLength() != 0) {
142             externalIp =  new StringBuilder(64).append(external.getIpAddress()).append("/").append(external.getPrefixLength()).toString();
143         }
144         IpMap ipm = new IpMapBuilder().setKey(new IpMapKey(internalIp)).setInternalIp(internalIp).setExternalIp(externalIp).build();
145         MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, getIpMapIdentifier(segmentId, internalIp), ipm);
146         LOG.debug("NAPT Service : registerMapping exit after updating DS with internalIP {}, externalIP {}", internalIp, externalIp);
147      }
148
149
150      /**
151       * method to get external ip/port mapping when provided with internal ip/port pair
152       * If already a mapping exist for the given input, then the existing mapping is returned
153       * instead of overwriting with new ip/port pair.
154       * @param segmentId
155       * @param sourceAddress - internal ip address/port pair
156       * @return external ip address/port
157       */
158      public SessionAddress getExternalAddressMapping(long segmentId, SessionAddress sourceAddress, NAPTEntryEvent.Protocol protocol) {
159          LOG.debug("NAPT Service : getExternalAddressMapping called with segmentId {}, internalIp {} and port {}",
160                  segmentId, sourceAddress.getIpAddress(), sourceAddress.getPortNumber());
161         /*
162          1. Get Internal IP, Port in IP:Port format
163          2. Inside DB with routerId get the list of entries and check if it matches with existing IP:Port
164          3. If True return SessionAddress of ExternalIp and Port
165          4. Else check ip Map and Form the ExternalIp and Port and update DB and then return ExternalIp and Port
166          */
167
168          //SessionAddress externalIpPort = new SessionAddress();
169          String internalIpPort = new StringBuilder(64).append(sourceAddress.getIpAddress()).append(":").append(sourceAddress.getPortNumber()).toString();
170
171          // First check existing Port Map.
172          SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort ,protocol);
173          if(existingIpPort != null) {
174              // populate externalIpPort from IpPortMap and return
175              LOG.debug("NAPT Service : getExternalAddressMapping successfully returning existingIpPort as {} and {}", existingIpPort.getIpAddress(), existingIpPort.getPortNumber());
176              return existingIpPort;
177          } else {
178              // Now check in ip-map
179              String externalIp = checkIpMap(segmentId, sourceAddress.getIpAddress());
180              if(externalIp == null) {
181                  LOG.error("NAPT Service : getExternalAddressMapping, Unexpected error, internal to external ip map does not exist");
182                  return null;
183              } else {
184                  /* Logic assuming internalIp is always ip and not subnet
185                   * case 1: externalIp is ip
186                   *        a) goto externalIp pool and getPort and return
187                   *        b) else return error
188                   * case 2: externalIp is subnet
189                   *        a) Take first externalIp and goto that Pool and getPort
190                   *             if port -> return
191                   *             else Take second externalIp and create that Pool and getPort
192                   *             if port ->return
193                   *             else
194                   *             Continue same with third externalIp till we exhaust subnet
195                   *        b) Nothing worked return error
196                   */
197                  SubnetUtils externalIpSubnet;
198                  List<String> allIps = new ArrayList<String>();
199                  String subnetPrefix = "/" + String.valueOf(NatConstants.DEFAULT_PREFIX);
200                  if( !externalIp.contains(subnetPrefix) ) {
201                     EXTSUBNET_FLAG = true;
202                     externalIpSubnet = new SubnetUtils(externalIp);
203                     allIps = Arrays.asList(externalIpSubnet.getInfo().getAllAddresses());
204                     LOG.debug("NAPT Service : total count of externalIps available {}", externalIpSubnet.getInfo().getAddressCount());
205                  } else {
206                      LOG.debug("NAPT Service : getExternalAddress single ip case");
207                      if(externalIp.contains(subnetPrefix)) {
208                          String[] externalIpSplit = externalIp.split("/");
209                          String extIp = externalIpSplit[0];
210                          externalIp = extIp; //remove /32 what we got from checkIpMap
211                      }
212                      allIps.add(externalIp);
213                  }
214
215                  for(String extIp : allIps) {
216                     LOG.info("NAPT Service : Looping externalIPs with externalIP now as {}", extIp);
217                     if(NEXT_EXTIP_FLAG) {
218                         createNaptPortPool(extIp);
219                         LOG.debug("NAPT Service : Created Pool for next Ext IP {}", extIp);
220                     }
221                     AllocateIdInput getIdInput = new AllocateIdInputBuilder()
222                         .setPoolName(extIp).setIdKey(internalIpPort)
223                         .build();
224                      try {
225                         Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
226                         RpcResult<AllocateIdOutput> rpcResult;
227                         if ((result != null) && (result.get().isSuccessful())) {
228                             LOG.debug("NAPT Service : Got id from idManager");
229                             rpcResult = result.get();
230                         } else {
231                             LOG.error("NAPT Service : getExternalAddressMapping, idManager could not allocate id retry if subnet");
232                             if(!EXTSUBNET_FLAG) {
233                                 LOG.error("NAPT Service : getExternalAddressMapping returning null for single IP case, may be ports exhausted");
234                                 return null;
235                             }
236                             LOG.debug("NAPT Service : Could be ports exhausted case, try with another externalIP if possible");
237                             NEXT_EXTIP_FLAG = true;
238                             continue;
239                         }
240                         int extPort= rpcResult.getResult().getIdValue().intValue();
241                         SessionAddress externalIpPort = new SessionAddress(extIp, extPort);
242                         // Write to ip-port-map before returning
243                         IpPortExternalBuilder ipExt = new IpPortExternalBuilder();
244                         IpPortExternal ipPortExt = ipExt.setIpAddress(extIp).setPortNum(extPort).build();
245                         IpPortMap ipm = new IpPortMapBuilder().setKey(new IpPortMapKey(internalIpPort))
246                                 .setIpPortInternal(internalIpPort).setIpPortExternal(ipPortExt).build();
247                         LOG.debug("NAPT Service : getExternalAddressMapping writing into ip-port-map with externalIP {} and port {}",
248                                 ipPortExt.getIpAddress(), ipPortExt.getPortNum());
249                         try {
250                             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
251                                            getIpPortMapIdentifier(segmentId, internalIpPort, protocol), ipm);
252                         } catch (UncheckedExecutionException uee) {
253                             LOG.error("NAPT Service : Failed to write into ip-port-map with exception {}", uee.getMessage() );
254                         }
255
256                          // Write to snat-internal-ip-port-info
257                          String internalIpAddress = sourceAddress.getIpAddress();
258                          int ipPort = sourceAddress.getPortNumber();
259                          ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
260                          List<Integer> portList = NatUtil.getInternalIpPortListInfo(broker,segmentId,internalIpAddress,protocolType);
261                          if (portList == null) {
262                              portList = Lists.newArrayList();
263                          }
264                          portList.add(ipPort);
265
266                          IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
267                          IntIpProtoType intIpProtocolType = builder.setKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
268                          try {
269                              MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, NatUtil.buildSnatIntIpPortIdentifier(segmentId, internalIpAddress, protocolType), intIpProtocolType);
270                          } catch (Exception ex) {
271                              LOG.error("NAPT Service : Failed to write into snat-internal-ip-port-info with exception {}", ex.getMessage() );
272                          }
273
274                          LOG.debug("NAPT Service : getExternalAddressMapping successfully returning externalIP {} and port {}",
275                                          externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
276                         return externalIpPort;
277                     } catch(InterruptedException | ExecutionException  e) {
278                         LOG.error("NAPT Service : getExternalAddressMapping, Exception caught  {}",e);
279                         return null;
280                     }
281                 }// end of for loop
282              }// end of else ipmap present
283          }// end of else check ipmap
284          LOG.error("NAPT Service: getExternalAddressMapping returning null, nothing worked or externalIPs exhausted");
285          return null;
286      }
287
288
289      /**
290       * release the existing mapping of internal ip/port to external ip/port pair
291       * if no mapping exist for given internal ip/port, it returns false
292       * @param segmentId
293       * @param address
294       * @return true if mapping exist and the mapping is removed successfully
295       */
296
297      public boolean releaseAddressMapping(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
298
299          LOG.debug("NAPT Service : releaseAddressMapping called with segmentId {}, internalIP {}, port {}", segmentId, address.getIpAddress(), address.getPortNumber());
300          // delete entry from IpPort Map and IP Map if exists
301          String internalIpPort = new StringBuilder(64).append(address.getIpAddress()).append(":").append(address.getPortNumber()).toString();
302          SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
303          if(existingIpPort != null) {
304              // delete the entry from IpPortMap DS
305              try {
306                  removeFromIpPortMapDS(segmentId, internalIpPort , protocol);
307              } catch (Exception e){
308                  LOG.error("NAPT Service : releaseAddressMapping failed, Removal of ipportmap {} for router {} failed {}" , internalIpPort, segmentId, e);
309                  return false;
310              }
311          } else {
312              LOG.error("NAPT Service : releaseAddressMapping failed, segmentId {} and internalIpPort {} not found in IpPortMap DS", segmentId, internalIpPort);
313              return false;
314          }
315          String existingIp = checkIpMap(segmentId, address.getIpAddress());
316          if(existingIp != null) {
317              // delete the entry from IpMap DS
318              try {
319                  removeFromIpMapDS(segmentId, address.getIpAddress());
320              } catch (Exception e){
321                  LOG.error("NAPT Service : Removal of  ipmap {} for router {} failed {}" , address.getIpAddress(), segmentId, e);
322                  return false;
323              }
324              //delete the entry from snatIntIpportinfo
325              try {
326                  removeFromSnatIpPortDS(segmentId, address.getIpAddress());
327              } catch (Exception e){
328                  LOG.error("NAPT Service : releaseAddressMapping failed, Removal of snatipportmap {} for router {} failed {}" , address.getIpAddress(), segmentId, e);
329                  return false;
330              }
331          } else {
332              LOG.error("NAPT Service : releaseAddressMapping failed, segmentId {} and internalIpPort {} not found in IpMap DS", segmentId, internalIpPort);
333              return false;
334          }
335          // Finally release port from idmanager
336          removePortFromPool(internalIpPort, existingIpPort.getIpAddress());
337
338          LOG.debug("NAPT Service : Exit of releaseAddressMapping successfully for segmentId {} and internalIpPort {}", segmentId, internalIpPort);  
339          return true;
340
341      }
342
343     protected void releaseIpExtPortMapping(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
344         String internalIpPort = address.getIpAddress() + ":" + address.getPortNumber();
345         SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
346         if(existingIpPort != null) {
347             // delete the entry from IpPortMap DS
348             try {
349                 removeFromIpPortMapDS(segmentId, internalIpPort , protocol);
350                 // Finally release port from idmanager
351                 removePortFromPool(internalIpPort, existingIpPort.getIpAddress());
352             } catch (Exception e){
353                 LOG.error("NAPT Service : releaseAddressMapping failed, Removal of ipportmap {} for router {} failed {}" ,
354                         internalIpPort, segmentId, e);
355             }
356         } else {
357             LOG.error("NAPT Service : releaseIpExtPortMapping failed, segmentId {} and internalIpPort {} not found in IpPortMap DS", segmentId, internalIpPort);
358         }
359
360         //delete the entry of port for InternalIp from snatIntIpportMappingDS
361         try {
362             removeSnatIntIpPortDS(segmentId,address, protocol);
363         } catch (Exception e){
364             LOG.error("NAPT Service : releaseSnatIpPortMapping failed, Removal of snatipportmap {} for router {} failed {}" ,
365                     address.getIpAddress(), segmentId, e);
366         }
367     }
368
369      /**
370       * removes the internal ip to external ip mapping if present
371       * @param segmentId
372       * @return true if successfully removed
373       */
374      public boolean removeMapping(long segmentId) {
375          try {
376              removeIpMappingForRouterID(segmentId);
377          } catch (Exception e){
378              LOG.error("NAPT Service : Removal of  IPMapping for router {} failed {}" , segmentId, e);
379              return false;
380          }
381
382          //TODO :  This is when router is deleted then cleanup the entries in tables, ports etc - Delete scenarios
383         return false;
384      }
385
386      // 2. Utility functions
387      protected InstanceIdentifier<IpMap> getIpMapIdentifier(long segid, String internal) {
388          InstanceIdentifier<IpMap> id = InstanceIdentifier.builder(
389                  IntextIpMap.class).child(IpMapping.class, new IpMappingKey(segid)).child(IpMap.class, new IpMapKey(internal)).build();
390          return id;
391      }
392
393     public static List<IpMap> getIpMapList(DataBroker broker, Long routerId) {
394         InstanceIdentifier id = getIpMapList(routerId);
395         Optional<IpMapping> ipMappingListData = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
396         if (ipMappingListData.isPresent()) {
397             IpMapping ipMapping = ipMappingListData.get();
398             return ipMapping.getIpMap();
399         }
400         return null;
401     }
402
403     protected static InstanceIdentifier<IpMapping> getIpMapList(long routerId) {
404         InstanceIdentifier<IpMapping> id = InstanceIdentifier.builder(
405                 IntextIpMap.class).child(IpMapping.class, new IpMappingKey(routerId)).build();
406         return id;
407     }
408
409      protected InstanceIdentifier<IpPortMap> getIpPortMapIdentifier(long segid, String internal, NAPTEntryEvent.Protocol protocol) {
410          ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
411          InstanceIdentifier<IpPortMap> id = InstanceIdentifier.builder(
412                  IntextIpPortMap.class).child(IpPortMapping.class, new IpPortMappingKey(segid)).child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType)).
413                  child(IpPortMap.class, new IpPortMapKey(internal)).build();
414          return id;
415      }
416
417      protected SessionAddress checkIpPortMap(long segmentId, String internalIpPort, NAPTEntryEvent.Protocol protocol) {
418
419          LOG.debug("NAPT Service : checkIpPortMap called with segmentId {} and internalIpPort {}", segmentId, internalIpPort);
420          ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
421          // check if ip-port-map node is there
422          InstanceIdentifierBuilder<IntextIpProtocolType> idBuilder =
423                          InstanceIdentifier.builder(IntextIpPortMap.class).child(IpPortMapping.class, new IpPortMappingKey(segmentId)).child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType));
424          InstanceIdentifier<IntextIpProtocolType> id = idBuilder.build();
425          Optional<IntextIpProtocolType> intextIpProtocolType = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
426          if (intextIpProtocolType.isPresent()) {
427                List<IpPortMap> ipPortMaps = intextIpProtocolType.get().getIpPortMap();
428                for (IpPortMap ipPortMap : ipPortMaps) {
429                     if (ipPortMap.getIpPortInternal().equals(internalIpPort)) {
430                        LOG.debug("NAPT Service : IpPortMap : {}", ipPortMap);
431                        SessionAddress externalIpPort = new SessionAddress(ipPortMap.getIpPortExternal().getIpAddress(),
432                                 ipPortMap.getIpPortExternal().getPortNum());
433                        LOG.debug("NAPT Service : checkIpPortMap returning successfully externalIP {} and port {}",
434                                externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
435                        return externalIpPort;
436                     }
437                }
438          }
439          // return null if not found
440          LOG.error("NAPT Service : no-entry in checkIpPortMap, returning NULL [should be OK] for segmentId {} and internalIPPort {}", segmentId, internalIpPort);
441          return null;
442      }
443
444      protected String checkIpMap(long segmentId, String internalIp) {
445
446          LOG.debug("NAPT Service : checkIpMap called with segmentId {} and internalIp {}", segmentId, internalIp);
447          String externalIp;
448          // check if ip-map node is there
449          InstanceIdentifierBuilder<IpMapping> idBuilder =
450                          InstanceIdentifier.builder(IntextIpMap.class).child(IpMapping.class, new IpMappingKey(segmentId));
451          InstanceIdentifier<IpMapping> id = idBuilder.build();
452          Optional<IpMapping> ipMapping = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
453          if (ipMapping.isPresent()) {
454                List<IpMap> ipMaps = ipMapping.get().getIpMap();
455                for (IpMap ipMap : ipMaps) {
456                     if (ipMap.getInternalIp().equals(internalIp)) {
457                        LOG.debug("NAPT Service : IpMap : {}", ipMap);
458                        externalIp = ipMap.getExternalIp().toString();
459                        LOG.debug("NAPT Service : checkIpMap successfully returning externalIp {}", externalIp );
460                        return externalIp;
461                     } else if (ipMap.getInternalIp().contains("/")) { // subnet case
462                         SubnetUtils subnetUtils = new SubnetUtils(ipMap.getInternalIp());
463                         SubnetInfo subnetInfo = subnetUtils.getInfo();
464                         if (subnetInfo.isInRange(internalIp)) {
465                             LOG.debug("NAPT Service : internalIp {} found to be IpMap of internalIpSubnet {}", internalIp, ipMap.getInternalIp());
466                             externalIp = ipMap.getExternalIp().toString();
467                             LOG.debug("NAPT Service : checkIpMap successfully returning externalIp {}", externalIp );
468                             return externalIp;
469                         }
470                     }
471                }
472          }
473          // return null if not found
474          LOG.error("NAPT Service : checkIpMap failed, returning NULL for segmentId {} and internalIp {}", segmentId, internalIp);
475          return null;
476       }
477
478     protected void removeSnatIntIpPortDS(long segmentId, SessionAddress address,NAPTEntryEvent.Protocol protocol) {
479         LOG.trace("NAPT Service : removeSnatIntIpPortDS method called for IntIpport {} of router {} ",address,segmentId);
480         ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
481         List<Integer> portList = NatUtil.getInternalIpPortListInfo(broker,segmentId,address.getIpAddress(),protocolType);
482         if (portList == null || portList.isEmpty() || !portList.contains(address.getPortNumber())) {
483            LOG.debug("Internal IP {} for port {} entry not found in SnatIntIpPort DS",address.getIpAddress(),address.getPortNumber());
484            return;
485         }
486         LOG.trace("NAPT Service : PortList {} retrieved for InternalIp {} of router {}",portList,address.getIpAddress(),segmentId);
487         Integer port = address.getPortNumber();
488         portList.remove(port);
489
490         IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
491         IntIpProtoType intIpProtocolType = builder.setKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
492         try {
493             MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, NatUtil.buildSnatIntIpPortIdentifier(segmentId, address.getIpAddress(), protocolType), intIpProtocolType);
494         } catch (Exception ex) {
495             LOG.error("NAPT Service : Failed to write into snat-internal-ip-port-info with exception {}", ex.getMessage() );
496         }
497         LOG.debug("NAPT Service : Removing SnatIp {} Port {} of router {} from SNATIntIpport datastore : {}"
498                 ,address.getIpAddress(),address.getPortNumber(),segmentId);
499     }
500
501     protected void removeFromSnatIpPortDS(long segmentId, String internalIp) {
502         InstanceIdentifier<IpPort> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class).child
503                 (IntipPortMap.class, new IntipPortMapKey(segmentId)).child(IpPort.class, new IpPortKey(internalIp)).build();
504         // remove from SnatIpPortDS
505         LOG.debug("NAPT Service : Removing SnatIpPort from datastore : {}", intIp);
506         MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, intIp);
507
508     }
509
510     protected void removeFromIpPortMapDS(long segmentId, String internalIpPort, NAPTEntryEvent.Protocol protocol) {
511          ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
512          InstanceIdentifierBuilder<IpPortMap> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
513                  .child(IpPortMapping.class, new IpPortMappingKey(segmentId)).child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
514                  .child(IpPortMap.class, new IpPortMapKey(internalIpPort));
515          InstanceIdentifier<IpPortMap> id = idBuilder.build();
516          // remove from ipportmap DS
517          LOG.debug("NAPT Service : Removing ipportmap from datastore : {}", id);
518          MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
519     }
520
521      protected void removeFromIpMapDS(long segmentId, String internalIp) {
522          InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
523                  .child(IpMapping.class, new IpMappingKey(segmentId))
524                  .child(IpMap.class, new IpMapKey(internalIp));
525          InstanceIdentifier<IpMap> id = idBuilder.build();
526          // remove from ipmap DS
527          LOG.debug("NAPT Service : Removing ipmap from datastore : {}", id);
528          MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
529      }
530
531     private void removeIpMappingForRouterID(long segmentId) {
532         InstanceIdentifierBuilder<IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
533                 .child(IpMapping.class, new IpMappingKey(segmentId));
534         InstanceIdentifier<IpMapping> id = idBuilder.build();
535         // remove from ipmap DS
536         LOG.debug("NAPT Service : Removing ipmap from datastore : {}", id);
537         MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
538     }
539
540      protected void removePortFromPool(String internalIpPort, String externalIp) {
541          LOG.debug("NAPT Service : removePortFromPool method called");
542          ReleaseIdInput idInput = new ReleaseIdInputBuilder().
543                                         setPoolName(externalIp)
544                                         .setIdKey(internalIpPort).build();
545          try {
546              Future<RpcResult<Void>> result = idManager.releaseId(idInput);
547              RpcResult<Void> rpcResult = result.get();
548              if(!rpcResult.isSuccessful()) {
549                  LOG.error("NAPT Service : idmanager failed to remove port from pool {}", rpcResult.getErrors());
550              }
551              LOG.debug("NAPT Service : Removed port from pool for InternalIpPort {} with externalIp {}",internalIpPort,externalIp);
552          } catch (InterruptedException | ExecutionException e) {
553              LOG.error("NAPT Service : idmanager failed with Exception {} when removing entry in pool with key {}, ", e, internalIpPort);
554          }
555      }
556 }