Java tutorial
/* * Copyright 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ /* * Created eyugsar 2016/12/1 */ package org.opendaylight.netvirt.natservice.internal; import com.google.common.base.Optional; import com.google.common.util.concurrent.UncheckedExecutionException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.apache.commons.net.util.SubnetUtils; import org.apache.commons.net.util.SubnetUtils.SubnetInfo; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.genius.mdsalutil.MDSALUtil; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpMap; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.SnatintIpPortMap; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCountersKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounterBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounterKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMappingKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolTypeKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapKey; 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; 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; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMap; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMapKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPortKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class NaptManager { private static final Logger LOG = LoggerFactory.getLogger(NaptManager.class); private final DataBroker dataBroker; private final IdManagerService idManager; private static final long LOW_PORT = 49152L; private static final long HIGH_PORT = 65535L; private static boolean EXTSUBNET_FLAG = false; private static boolean NEXT_EXTIP_FLAG = false; public NaptManager(final DataBroker dataBroker, final IdManagerService idManager) { this.dataBroker = dataBroker; this.idManager = idManager; } protected void createNaptPortPool(String poolName) { LOG.debug("NAPT Service : createPortPool requested for : {}", poolName); CreateIdPoolInput createPool = new CreateIdPoolInputBuilder().setPoolName(poolName).setLow(LOW_PORT) .setHigh(HIGH_PORT).build(); try { Future<RpcResult<Void>> result = idManager.createIdPool(createPool); if ((result != null) && (result.get().isSuccessful())) { LOG.debug("NAPT Service : Created PortPool"); } else { LOG.error("NAPT Service : Unable to create PortPool"); } } catch (InterruptedException | ExecutionException e) { LOG.error("Failed to create PortPool for NAPT Service", e); } } void removeNaptPortPool(String poolName) { DeleteIdPoolInput deleteIdPoolInput = new DeleteIdPoolInputBuilder().setPoolName(poolName).build(); LOG.debug("NAPT Service : Remove Napt port pool requested for : {}", poolName); try { Future<RpcResult<Void>> result = idManager.deleteIdPool(deleteIdPoolInput); if ((result != null) && (result.get().isSuccessful())) { LOG.debug("NAPT Service : Deleted PortPool {}", poolName); } else { LOG.error("NAPT Service : Unable to delete PortPool {}", poolName); } } catch (InterruptedException | ExecutionException e) { LOG.error("Failed to delete PortPool {} for NAPT Service", poolName, e); } } // 1. napt service functions /** * This method is used to inform this service of what external IP address to be used * as mapping when requested one for the internal IP address given in the input. * * @param segmentId segmentation in which the mapping to be used. Eg; routerid * @param internal subnet prefix or ip address * @param external subnet prefix or ip address */ public void registerMapping(long segmentId, IPAddress internal, IPAddress external) { LOG.debug( "NAPT Service : registerMapping called with segmentid {}, internalIp {}, prefix {}, externalIp {} " + "and prefix {} ", segmentId, internal.getIpAddress(), internal.getPrefixLength(), external.getIpAddress(), external.getPrefixLength()); // Create Pool per ExternalIp and not for all IPs in the subnet. // Create new Pools during getExternalAddressMapping if exhausted. String externalIpPool; // subnet case if (external.getPrefixLength() != 0 && external.getPrefixLength() != NatConstants.DEFAULT_PREFIX) { String externalSubnet = external.getIpAddress() + "/" + external.getPrefixLength(); LOG.debug("NAPT Service : externalSubnet is : {}", externalSubnet); SubnetUtils subnetUtils = new SubnetUtils(externalSubnet); SubnetInfo subnetInfo = subnetUtils.getInfo(); externalIpPool = subnetInfo.getLowAddress(); } else { // ip case externalIpPool = external.getIpAddress(); } createNaptPortPool(externalIpPool); // Store the ip to ip map in Operational DS String internalIp = internal.getIpAddress(); if (internal.getPrefixLength() != 0) { internalIp = internal.getIpAddress() + "/" + internal.getPrefixLength(); } String externalIp = external.getIpAddress(); if (external.getPrefixLength() != 0) { externalIp = external.getIpAddress() + "/" + external.getPrefixLength(); } updateCounter(segmentId, externalIp, true); //update the actual ip-map IpMap ipm = new IpMapBuilder().setKey(new IpMapKey(internalIp)).setInternalIp(internalIp) .setExternalIp(externalIp).build(); MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, getIpMapIdentifier(segmentId, internalIp), ipm); LOG.debug("NAPT Service : registerMapping exit after updating DS with internalIP {}, externalIP {}", internalIp, externalIp); } public void updateCounter(long segmentId, String externalIp, boolean isAdd) { short counter = 0; InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class) .child(ExternalCounters.class, new ExternalCountersKey(segmentId)) .child(ExternalIpCounter.class, new ExternalIpCounterKey(externalIp)).build(); Optional<ExternalIpCounter> externalIpCounter = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id); if (externalIpCounter.isPresent()) { counter = externalIpCounter.get().getCounter(); if (isAdd) { counter++; LOG.debug("NAT Service : externalIp and counter after increment are {} and {}", externalIp, counter); } else { if (counter > 0) { counter--; } LOG.debug("NAT Service : externalIp and counter after decrement are {} and {}", externalIp, counter); } } else if (isAdd) { counter = 1; } //update the new counter value for this externalIp ExternalIpCounter externalIpCounterData = new ExternalIpCounterBuilder() .setKey(new ExternalIpCounterKey(externalIp)).setExternalIp(externalIp).setCounter(counter).build(); MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, getExternalIpsIdentifier(segmentId, externalIp), externalIpCounterData); } /** * method to get external ip/port mapping when provided with internal ip/port pair * If already a mapping exist for the given input, then the existing mapping is returned * instead of overwriting with new ip/port pair. * * @param segmentId - Router ID * @param sourceAddress - internal ip address/port pair * @param protocol - TCP/UDP * @return external ip address/port */ // TODO Clean up the exception handling @SuppressWarnings("checkstyle:IllegalCatch") public SessionAddress getExternalAddressMapping(long segmentId, SessionAddress sourceAddress, NAPTEntryEvent.Protocol protocol) { LOG.debug("NAPT Service : getExternalAddressMapping called with segmentId {}, internalIp {} and port {}", segmentId, sourceAddress.getIpAddress(), sourceAddress.getPortNumber()); /* 1. Get Internal IP, Port in IP:Port format 2. Inside DB with routerId get the list of entries and check if it matches with existing IP:Port 3. If True return SessionAddress of ExternalIp and Port 4. Else check ip Map and Form the ExternalIp and Port and update DB and then return ExternalIp and Port */ //SessionAddress externalIpPort = new SessionAddress(); String internalIpPort = sourceAddress.getIpAddress() + ":" + sourceAddress.getPortNumber(); // First check existing Port Map. SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol); if (existingIpPort != null) { // populate externalIpPort from IpPortMap and return LOG.debug("NAPT Service : getExternalAddressMapping successfully returning existingIpPort as {} and {}", existingIpPort.getIpAddress(), existingIpPort.getPortNumber()); return existingIpPort; } else { // Now check in ip-map String externalIp = checkIpMap(segmentId, sourceAddress.getIpAddress()); if (externalIp == null) { LOG.error("NAPT Service : getExternalAddressMapping, Unexpected error, internal to external " + "ip map does not exist"); return null; } else { /* Logic assuming internalIp is always ip and not subnet * case 1: externalIp is ip * a) goto externalIp pool and getPort and return * b) else return error * case 2: externalIp is subnet * a) Take first externalIp and goto that Pool and getPort * if port -> return * else Take second externalIp and create that Pool and getPort * if port ->return * else * Continue same with third externalIp till we exhaust subnet * b) Nothing worked return error */ SubnetUtils externalIpSubnet; List<String> allIps = new ArrayList<>(); String subnetPrefix = "/" + String.valueOf(NatConstants.DEFAULT_PREFIX); if (!externalIp.contains(subnetPrefix)) { EXTSUBNET_FLAG = true; externalIpSubnet = new SubnetUtils(externalIp); allIps = Arrays.asList(externalIpSubnet.getInfo().getAllAddresses()); LOG.debug("NAPT Service : total count of externalIps available {}", externalIpSubnet.getInfo().getAddressCount()); } else { LOG.debug("NAPT Service : getExternalAddress single ip case"); if (externalIp.contains(subnetPrefix)) { //remove /32 what we got from checkIpMap externalIp = externalIp.substring(0, externalIp.indexOf(subnetPrefix)); } allIps.add(externalIp); } for (String extIp : allIps) { LOG.info("NAPT Service : Looping externalIPs with externalIP now as {}", extIp); if (NEXT_EXTIP_FLAG) { createNaptPortPool(extIp); LOG.debug("NAPT Service : Created Pool for next Ext IP {}", extIp); } AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(extIp) .setIdKey(internalIpPort).build(); try { Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput); RpcResult<AllocateIdOutput> rpcResult; if ((result != null) && (result.get().isSuccessful())) { LOG.debug("NAPT Service : Got id from idManager"); rpcResult = result.get(); } else { LOG.error("NAPT Service : getExternalAddressMapping, idManager could not " + "allocate id retry if subnet"); if (!EXTSUBNET_FLAG) { LOG.error( "NAPT Service : getExternalAddressMapping returning null for single IP case," + " may be ports exhausted"); return null; } LOG.debug("NAPT Service : Could be ports exhausted case, try with another externalIP" + " if possible"); NEXT_EXTIP_FLAG = true; continue; } int extPort = rpcResult.getResult().getIdValue().intValue(); // Write to ip-port-map before returning IpPortExternalBuilder ipExt = new IpPortExternalBuilder(); IpPortExternal ipPortExt = ipExt.setIpAddress(extIp).setPortNum(extPort).build(); IpPortMap ipm = new IpPortMapBuilder().setKey(new IpPortMapKey(internalIpPort)) .setIpPortInternal(internalIpPort).setIpPortExternal(ipPortExt).build(); LOG.debug( "NAPT Service : getExternalAddressMapping writing into ip-port-map with " + "externalIP {} and port {}", ipPortExt.getIpAddress(), ipPortExt.getPortNum()); try { MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getIpPortMapIdentifier(segmentId, internalIpPort, protocol), ipm); } catch (UncheckedExecutionException uee) { LOG.error("NAPT Service : Failed to write into ip-port-map with exception {}", uee.getMessage()); } // Write to snat-internal-ip-port-info String internalIpAddress = sourceAddress.getIpAddress(); int ipPort = sourceAddress.getPortNumber(); ProtocolTypes protocolType = NatUtil.getProtocolType(protocol); List<Integer> portList = NatUtil.getInternalIpPortListInfo(dataBroker, segmentId, internalIpAddress, protocolType); if (portList == null) { portList = new ArrayList<>(); } portList.add(ipPort); IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder(); IntIpProtoType intIpProtocolType = builder.setKey(new IntIpProtoTypeKey(protocolType)) .setPorts(portList).build(); try { MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, NatUtil .buildSnatIntIpPortIdentifier(segmentId, internalIpAddress, protocolType), intIpProtocolType); } catch (Exception ex) { LOG.error("NAPT Service : Failed to write into snat-internal-ip-port-info with " + "exception {}", ex.getMessage()); } SessionAddress externalIpPort = new SessionAddress(extIp, extPort); LOG.debug( "NAPT Service : getExternalAddressMapping successfully returning externalIP {} " + "and port {}", externalIpPort.getIpAddress(), externalIpPort.getPortNumber()); return externalIpPort; } catch (InterruptedException | ExecutionException e) { LOG.error("NAPT Service : getExternalAddressMapping, Exception caught {}", e); return null; } } // end of for loop } // end of else ipmap present } // end of else check ipmap LOG.error( "NAPT Service: getExternalAddressMapping returning null, nothing worked or externalIPs exhausted"); return null; } /** * Release the existing mapping of internal ip/port to external ip/port pair * if no mapping exist for given internal ip/port, it returns false. * * @param segmentId - Router ID * @param address - Session Address * @param protocol - TCP/UDP * @return true if mapping exist and the mapping is removed successfully */ // TODO Clean up the exception handling @SuppressWarnings("checkstyle:IllegalCatch") public boolean releaseAddressMapping(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) { LOG.debug("NAPT Service : releaseAddressMapping called with segmentId {}, internalIP {}, port {}", segmentId, address.getIpAddress(), address.getPortNumber()); // delete entry from IpPort Map and IP Map if exists String internalIpPort = address.getIpAddress() + ":" + address.getPortNumber(); SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol); if (existingIpPort != null) { // delete the entry from IpPortMap DS try { removeFromIpPortMapDS(segmentId, internalIpPort, protocol); } catch (Exception e) { LOG.error("NAPT Service : releaseAddressMapping failed, Removal of ipportmap {} for " + "router {} failed {}", internalIpPort, segmentId, e); return false; } } else { LOG.error("NAPT Service : releaseAddressMapping failed, segmentId {} and internalIpPort {} " + "not found in IpPortMap DS", segmentId, internalIpPort); return false; } String existingIp = checkIpMap(segmentId, address.getIpAddress()); if (existingIp != null) { // delete the entry from IpMap DS try { removeFromIpMapDS(segmentId, address.getIpAddress()); } catch (Exception e) { LOG.error("NAPT Service : Removal of ipmap {} for router {} failed {}", address.getIpAddress(), segmentId, e); return false; } //delete the entry from snatIntIpportinfo try { removeFromSnatIpPortDS(segmentId, address.getIpAddress()); } catch (Exception e) { LOG.error("NAPT Service : releaseAddressMapping failed, Removal of snatipportmap {} for " + "router {} failed {}", address.getIpAddress(), segmentId, e); return false; } } else { LOG.error("NAPT Service : releaseAddressMapping failed, segmentId {} and internalIpPort {} " + "not found in IpMap DS", segmentId, internalIpPort); return false; } // Finally release port from idmanager removePortFromPool(internalIpPort, existingIpPort.getIpAddress()); LOG.debug("NAPT Service : Exit of releaseAddressMapping successfully for segmentId {} and " + "internalIpPort {}", segmentId, internalIpPort); return true; } // TODO Clean up the exception handling @SuppressWarnings("checkstyle:IllegalCatch") protected void releaseIpExtPortMapping(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) { String internalIpPort = address.getIpAddress() + ":" + address.getPortNumber(); SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol); if (existingIpPort != null) { // delete the entry from IpPortMap DS try { removeFromIpPortMapDS(segmentId, internalIpPort, protocol); // Finally release port from idmanager removePortFromPool(internalIpPort, existingIpPort.getIpAddress()); } catch (Exception e) { LOG.error("NAPT Service : releaseAddressMapping failed, Removal of ipportmap {} for " + "router {} failed {}", internalIpPort, segmentId, e); } } else { LOG.error("NAPT Service : releaseIpExtPortMapping failed, segmentId {} and " + "internalIpPort {} not found in IpPortMap DS", segmentId, internalIpPort); } //delete the entry of port for InternalIp from snatIntIpportMappingDS try { removeSnatIntIpPortDS(segmentId, address, protocol); } catch (Exception e) { LOG.error("NAPT Service : releaseSnatIpPortMapping failed, Removal of snatipportmap {} for " + "router {} failed {}", address.getIpAddress(), segmentId, e); } } /** * Removes the internal ip to external ip mapping if present. * * @param segmentId - Router ID * @return true if successfully removed */ // TODO Clean up the exception handling @SuppressWarnings("checkstyle:IllegalCatch") public boolean removeMapping(long segmentId) { try { removeIpMappingForRouterID(segmentId); removeIpPortMappingForRouterID(segmentId); removeIntIpPortMappingForRouterID(segmentId); } catch (Exception e) { LOG.error("NAPT Service : Removal of IPMapping for router {} failed {}", segmentId, e); return false; } //TODO : This is when router is deleted then cleanup the entries in tables, ports etc - Delete scenarios return false; } protected InstanceIdentifier<IpMap> getIpMapIdentifier(long segid, String internal) { InstanceIdentifier<IpMap> id = InstanceIdentifier.builder(IntextIpMap.class) .child(IpMapping.class, new IpMappingKey(segid)).child(IpMap.class, new IpMapKey(internal)).build(); return id; } protected InstanceIdentifier<ExternalIpCounter> getExternalIpsIdentifier(long segmentId, String external) { InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class) .child(ExternalCounters.class, new ExternalCountersKey(segmentId)) .child(ExternalIpCounter.class, new ExternalIpCounterKey(external)).build(); return id; } public static List<IpMap> getIpMapList(DataBroker broker, Long routerId) { InstanceIdentifier<IpMapping> id = getIpMapList(routerId); Optional<IpMapping> ipMappingListData = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id); if (ipMappingListData.isPresent()) { IpMapping ipMapping = ipMappingListData.get(); return ipMapping.getIpMap(); } return null; } protected static InstanceIdentifier<IpMapping> getIpMapList(long routerId) { InstanceIdentifier<IpMapping> id = InstanceIdentifier.builder(IntextIpMap.class) .child(IpMapping.class, new IpMappingKey(routerId)).build(); return id; } protected InstanceIdentifier<IpPortMap> getIpPortMapIdentifier(long segid, String internal, NAPTEntryEvent.Protocol protocol) { ProtocolTypes protocolType = NatUtil.getProtocolType(protocol); InstanceIdentifier<IpPortMap> id = InstanceIdentifier.builder(IntextIpPortMap.class) .child(IpPortMapping.class, new IpPortMappingKey(segid)) .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType)) .child(IpPortMap.class, new IpPortMapKey(internal)).build(); return id; } protected SessionAddress checkIpPortMap(long segmentId, String internalIpPort, NAPTEntryEvent.Protocol protocol) { LOG.debug("NAPT Service : checkIpPortMap called with segmentId {} and internalIpPort {}", segmentId, internalIpPort); ProtocolTypes protocolType = NatUtil.getProtocolType(protocol); // check if ip-port-map node is there InstanceIdentifierBuilder<IntextIpProtocolType> idBuilder = InstanceIdentifier .builder(IntextIpPortMap.class).child(IpPortMapping.class, new IpPortMappingKey(segmentId)) .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType)); InstanceIdentifier<IntextIpProtocolType> id = idBuilder.build(); Optional<IntextIpProtocolType> intextIpProtocolType = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id); if (intextIpProtocolType.isPresent()) { List<IpPortMap> ipPortMaps = intextIpProtocolType.get().getIpPortMap(); for (IpPortMap ipPortMap : ipPortMaps) { if (ipPortMap.getIpPortInternal().equals(internalIpPort)) { LOG.debug("NAPT Service : IpPortMap : {}", ipPortMap); SessionAddress externalIpPort = new SessionAddress(ipPortMap.getIpPortExternal().getIpAddress(), ipPortMap.getIpPortExternal().getPortNum()); LOG.debug("NAPT Service : checkIpPortMap returning successfully externalIP {} and port {}", externalIpPort.getIpAddress(), externalIpPort.getPortNumber()); return externalIpPort; } } } // return null if not found LOG.error("NAPT Service : no-entry in checkIpPortMap, returning NULL [should be OK] for " + "segmentId {} and internalIPPort {}", segmentId, internalIpPort); return null; } protected String checkIpMap(long segmentId, String internalIp) { LOG.debug("NAPT Service : checkIpMap called with segmentId {} and internalIp {}", segmentId, internalIp); String externalIp; // check if ip-map node is there InstanceIdentifierBuilder<IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class) .child(IpMapping.class, new IpMappingKey(segmentId)); InstanceIdentifier<IpMapping> id = idBuilder.build(); Optional<IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id); if (ipMapping.isPresent()) { List<IpMap> ipMaps = ipMapping.get().getIpMap(); for (IpMap ipMap : ipMaps) { if (ipMap.getInternalIp().equals(internalIp)) { LOG.debug("NAPT Service : IpMap : {}", ipMap); externalIp = ipMap.getExternalIp(); LOG.debug("NAPT Service : checkIpMap successfully returning externalIp {}", externalIp); return externalIp; } else if (ipMap.getInternalIp().contains("/")) { // subnet case SubnetUtils subnetUtils = new SubnetUtils(ipMap.getInternalIp()); SubnetInfo subnetInfo = subnetUtils.getInfo(); if (subnetInfo.isInRange(internalIp)) { LOG.debug("NAPT Service : internalIp {} found to be IpMap of internalIpSubnet {}", internalIp, ipMap.getInternalIp()); externalIp = ipMap.getExternalIp(); LOG.debug("NAPT Service : checkIpMap successfully returning externalIp {}", externalIp); return externalIp; } } } } // return null if not found LOG.error("NAPT Service : checkIpMap failed, returning NULL for segmentId {} and internalIp {}", segmentId, internalIp); return null; } // TODO Clean up the exception handling @SuppressWarnings("checkstyle:IllegalCatch") protected void removeSnatIntIpPortDS(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) { LOG.trace("NAPT Service : removeSnatIntIpPortDS method called for IntIpport {} of router {} ", address, segmentId); ProtocolTypes protocolType = NatUtil.getProtocolType(protocol); List<Integer> portList = NatUtil.getInternalIpPortListInfo(dataBroker, segmentId, address.getIpAddress(), protocolType); if (portList == null || portList.isEmpty() || !portList.contains(address.getPortNumber())) { LOG.debug("Internal IP {} for port {} entry not found in SnatIntIpPort DS", address.getIpAddress(), address.getPortNumber()); return; } LOG.trace("NAPT Service : PortList {} retrieved for InternalIp {} of router {}", portList, address.getIpAddress(), segmentId); Integer port = address.getPortNumber(); portList.remove(port); IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder(); IntIpProtoType intIpProtocolType = builder.setKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList) .build(); try { MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, NatUtil.buildSnatIntIpPortIdentifier(segmentId, address.getIpAddress(), protocolType), intIpProtocolType); } catch (Exception ex) { LOG.error("NAPT Service : Failed to write into snat-internal-ip-port-info with exception {}", ex.getMessage()); } LOG.debug("NAPT Service : Removing SnatIp {} Port {} of router {} from SNATIntIpport datastore : {}", address.getIpAddress(), address.getPortNumber(), segmentId); } protected void removeFromSnatIpPortDS(long segmentId, String internalIp) { InstanceIdentifier<IpPort> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class) .child(IntipPortMap.class, new IntipPortMapKey(segmentId)) .child(IpPort.class, new IpPortKey(internalIp)).build(); // remove from SnatIpPortDS LOG.debug("NAPT Service : Removing SnatIpPort from datastore : {}", intIp); MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp); } protected void removeFromIpPortMapDS(long segmentId, String internalIpPort, NAPTEntryEvent.Protocol protocol) { ProtocolTypes protocolType = NatUtil.getProtocolType(protocol); removeFromIpPortMapDS(segmentId, internalIpPort, protocolType); } protected void removeFromIpPortMapDS(long segmentId, String internalIpPort, ProtocolTypes protocolType) { InstanceIdentifierBuilder<IpPortMap> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class) .child(IpPortMapping.class, new IpPortMappingKey(segmentId)) .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType)) .child(IpPortMap.class, new IpPortMapKey(internalIpPort)); InstanceIdentifier<IpPortMap> id = idBuilder.build(); // remove from ipportmap DS LOG.debug("NAPT Service : Removing ipportmap from datastore : {}", id); MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id); } protected void removeFromIpMapDS(long segmentId, String internalIp) { InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class) .child(IpMapping.class, new IpMappingKey(segmentId)).child(IpMap.class, new IpMapKey(internalIp)); InstanceIdentifier<IpMap> id = idBuilder.build(); // Get externalIp and decrement the counter String externalIp = null; Optional<IpMap> ipMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id); if (ipMap.isPresent()) { externalIp = ipMap.get().getExternalIp(); LOG.debug("NAT Service : externalIP is {}", externalIp); } else { LOG.warn("NAT Service : ipMap not present for the internal IP {}", internalIp); } if (externalIp != null) { updateCounter(segmentId, externalIp, false); // remove from ipmap DS LOG.debug("NAPT Service : Removing ipmap from datastore"); MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id); } else { LOG.warn("NAT Service : externalIp not present for the internal IP {}", internalIp); } } protected void removeIntExtIpMapDS(long segmentId, String internalIp) { InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class) .child(IpMapping.class, new IpMappingKey(segmentId)).child(IpMap.class, new IpMapKey(internalIp)); InstanceIdentifier<IpMap> id = idBuilder.build(); LOG.debug("NAPT Service : Removing ipmap from datastore"); MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id); } protected String getExternalIpAllocatedForSubnet(long segmentId, String internalIp) { InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class) .child(IpMapping.class, new IpMappingKey(segmentId)).child(IpMap.class, new IpMapKey(internalIp)); InstanceIdentifier<IpMap> id = idBuilder.build(); Optional<IpMap> ipMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id); if (ipMap.isPresent()) { return ipMap.get().getExternalIp(); } return null; } private void removeIpMappingForRouterID(long segmentId) { InstanceIdentifierBuilder<IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class) .child(IpMapping.class, new IpMappingKey(segmentId)); InstanceIdentifier<IpMapping> id = idBuilder.build(); // Get all externalIps and decrement their counters before deleting the ipmap String externalIp = null; Optional<IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id); if (ipMapping.isPresent()) { List<IpMap> ipMaps = ipMapping.get().getIpMap(); for (IpMap ipMap : ipMaps) { externalIp = ipMap.getExternalIp(); LOG.debug("NAT Service : externalIP is {}", externalIp); if (externalIp != null) { updateCounter(segmentId, externalIp, false); } } } // remove from ipmap DS LOG.debug("NAPT Service : Removing Ipmap for router {} from datastore", segmentId); MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id); } void removeIpPortMappingForRouterID(long segmentId) { InstanceIdentifier<IpPortMapping> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class) .child(IpPortMapping.class, new IpPortMappingKey(segmentId)).build(); // remove from IntExtIpPortmap DS LOG.debug("NAPT Service : Removing IntExtIpPort map for router {} from datastore", segmentId); MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, idBuilder); } void removeIntIpPortMappingForRouterID(long segmentId) { InstanceIdentifier<IntipPortMap> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class) .child(IntipPortMap.class, new IntipPortMapKey(segmentId)).build(); // remove from SnatIntIpPortmap DS LOG.debug("NAPT Service : Removing SnatIntIpPort from datastore : {}", intIp); MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, intIp); } void removePortFromPool(String internalIpPort, String externalIp) { LOG.debug("NAPT Service : removePortFromPool method called"); ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(externalIp).setIdKey(internalIpPort) .build(); try { Future<RpcResult<Void>> result = idManager.releaseId(idInput); RpcResult<Void> rpcResult = result.get(); if (!rpcResult.isSuccessful()) { LOG.error("NAPT Service : idmanager failed to remove port from pool {}", rpcResult.getErrors()); } LOG.debug("NAPT Service : Removed port from pool for InternalIpPort {} with externalIp {}", internalIpPort, externalIp); } catch (InterruptedException | ExecutionException e) { LOG.error("NAPT Service : idmanager failed with Exception {} when removing entry in pool with key {}, ", e, internalIpPort); } } protected void initialiseExternalCounter(Routers routers, long routerId) { LOG.debug("NAPT Service : Initialise External IPs counter"); List<ExternalIps> externalIps = routers.getExternalIps(); //update the new counter value for this externalIp for (ExternalIps externalIp : externalIps) { String[] ipSplit = externalIp.getIpAddress().split("/"); String extIp = ipSplit[0]; String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX); if (ipSplit.length == 2) { extPrefix = ipSplit[1]; } extIp = extIp + "/" + extPrefix; initialiseNewExternalIpCounter(routerId, extIp); } } protected void initialiseNewExternalIpCounter(long routerId, String externalIp) { ExternalIpCounter externalIpCounterData = new ExternalIpCounterBuilder() .setKey(new ExternalIpCounterKey(externalIp)).setExternalIp(externalIp).setCounter((short) 0) .build(); MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, getExternalIpsIdentifier(routerId, externalIp), externalIpCounterData); } protected void removeExternalCounter(long routerId) { // Remove from external-counters model InstanceIdentifier<ExternalCounters> id = InstanceIdentifier.builder(ExternalIpsCounter.class) .child(ExternalCounters.class, new ExternalCountersKey(routerId)).build(); LOG.debug("NAPT Service : Removing ExternalCounterd from datastore"); MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id); } protected void removeExternalIpCounter(long routerId, String externalIp) { // Remove from external-counters model InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class) .child(ExternalCounters.class, new ExternalCountersKey(routerId)) .child(ExternalIpCounter.class, new ExternalIpCounterKey(externalIp)).build(); LOG.debug("NAPT Service : Removing ExternalIpsCounter from datastore"); MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id); } }