Bug 8743 : Fix NAT Service to safely use vpn-to-dpn list.
[netvirt.git] / vpnservice / natservice / natservice-impl / src / main / java / org / opendaylight / netvirt / natservice / internal / NatUtil.java
1 /*
2  * Copyright © 2016, 2017 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 package org.opendaylight.netvirt.natservice.internal;
10
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.math.BigInteger;
16 import java.net.InetAddress;
17 import java.net.UnknownHostException;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Objects;
24 import java.util.Set;
25 import java.util.concurrent.ExecutionException;
26 import java.util.concurrent.Future;
27 import java.util.stream.Collectors;
28
29 import javax.annotation.Nonnull;
30 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
32 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
33 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
34 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
35 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
36 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
37 import org.opendaylight.genius.mdsalutil.ActionInfo;
38 import org.opendaylight.genius.mdsalutil.FlowEntity;
39 import org.opendaylight.genius.mdsalutil.FlowEntityBuilder;
40 import org.opendaylight.genius.mdsalutil.InstructionInfo;
41 import org.opendaylight.genius.mdsalutil.MDSALUtil;
42 import org.opendaylight.genius.mdsalutil.MatchInfo;
43 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
44 import org.opendaylight.genius.mdsalutil.NwConstants;
45 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
46 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
47 import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
48 import org.opendaylight.genius.mdsalutil.actions.ActionPushVlan;
49 import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
50 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldVlanVid;
51 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
52 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
53 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
54 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
55 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
56 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
57 import org.opendaylight.netvirt.elanmanager.api.IElanService;
58 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
59 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
60 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
61 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
62 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
63 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
64 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
65 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
66 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
68 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
69 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
70 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
71 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCase;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInputBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.DpnRouters;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.LearntVpnVipToPortData;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PrefixToInterface;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersList;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersListBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersListKey;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersList;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersListBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersListKey;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPortKey;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsKey;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalSubnets;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpPortInfo;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpMap;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterIdName;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterToVpnMapping;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.SnatintIpPortMap;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCountersKey;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.SubnetsKey;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPortsKey;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.PortsKey;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMapKey;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMapping;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingKey;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolTypeKey;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapKey;
171 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;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIds;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsBuilder;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsKey;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.to.vpn.mapping.Routermapping;
178 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.to.vpn.mapping.RoutermappingKey;
179 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMap;
180 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMapKey;
181 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
182 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPortKey;
183 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
184 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeKey;
185 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkMaps;
186 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
187 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
188 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
189 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
190 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey;
191 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
192 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
193 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
194 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
195 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
196 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
197 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
198 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.RouterKey;
199 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
200 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
201 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
202 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
203 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
204 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
205 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
206 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionResubmitRpcAddGroupCase;
207 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionRegLoadNodesNodeTableFlowApplyActionsCase;
208 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
209 import org.opendaylight.yangtools.yang.binding.DataObject;
210 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
211 import org.opendaylight.yangtools.yang.common.RpcResult;
212 import org.slf4j.Logger;
213 import org.slf4j.LoggerFactory;
214
215 public class NatUtil {
216
217     private static String OF_URI_SEPARATOR = ":";
218     private static final Logger LOG = LoggerFactory.getLogger(NatUtil.class);
219
220     /*
221      getCookieSnatFlow() computes and returns a unique cookie value for the NAT flows using the router ID as the
222       reference value.
223      */
224     public static BigInteger getCookieSnatFlow(long routerId) {
225         return NatConstants.COOKIE_NAPT_BASE.add(new BigInteger("0110000", 16)).add(
226             BigInteger.valueOf(routerId));
227     }
228
229     /*
230       getCookieNaptFlow() computes and returns a unique cookie value for the NAPT flows using the router ID as the
231        reference value.
232     */
233     public static BigInteger getCookieNaptFlow(long routerId) {
234         return NatConstants.COOKIE_NAPT_BASE.add(new BigInteger("0111000", 16)).add(
235             BigInteger.valueOf(routerId));
236     }
237
238     /*
239         getVpnId() returns the VPN ID from the VPN name
240      */
241     public static long getVpnId(DataBroker broker, String vpnName) {
242         if (vpnName == null) {
243             return NatConstants.INVALID_ID;
244         }
245
246         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
247             .instance.to.vpn.id.VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
248         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
249             .instance.to.vpn.id.VpnInstance> vpnInstance = read(broker, LogicalDatastoreType.CONFIGURATION, id);
250
251         long vpnId = NatConstants.INVALID_ID;
252         if (vpnInstance.isPresent()) {
253             Long vpnIdAsLong = vpnInstance.get().getVpnId();
254             if (vpnIdAsLong != null) {
255                 vpnId = vpnIdAsLong;
256             }
257         }
258         return vpnId;
259     }
260
261     public static Long getNetworkVpnIdFromRouterId(DataBroker broker, long routerId) {
262         //Get the external network ID from the ExternalRouter model
263         Uuid networkId = NatUtil.getNetworkIdFromRouterId(broker, routerId);
264         if (networkId == null) {
265             LOG.error("NAT Service : networkId is null");
266             return NatConstants.INVALID_ID;
267         }
268
269         //Get the VPN ID from the ExternalNetworks model
270         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(broker, networkId);
271         if (vpnUuid == null) {
272             LOG.error("NAT Service : vpnUuid is null");
273             return NatConstants.INVALID_ID;
274         }
275         Long vpnId = NatUtil.getVpnId(broker, vpnUuid.getValue());
276         return vpnId;
277     }
278
279     static InstanceIdentifier<RouterPorts> getRouterPortsId(String routerId) {
280         return InstanceIdentifier.builder(FloatingIpInfo.class)
281             .child(RouterPorts.class, new RouterPortsKey(routerId)).build();
282     }
283
284     static InstanceIdentifier<Routermapping> getRouterVpnMappingId(String routerId) {
285         return InstanceIdentifier.builder(RouterToVpnMapping.class)
286             .child(Routermapping.class, new RoutermappingKey(routerId)).build();
287     }
288
289     static InstanceIdentifier<Ports> getPortsIdentifier(String routerId, String portName) {
290         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId))
291             .child(Ports.class, new PortsKey(portName)).build();
292     }
293
294     static InstanceIdentifier<InternalToExternalPortMap> getIntExtPortMapIdentifier(String routerId, String portName,
295                                                                                     String internalIp) {
296         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId))
297             .child(Ports.class, new PortsKey(portName))
298             .child(InternalToExternalPortMap.class, new InternalToExternalPortMapKey(internalIp)).build();
299     }
300
301     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
302         .instance.to.vpn.id.VpnInstance> getVpnInstanceToVpnIdIdentifier(String vpnName) {
303         return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
304             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
305                     .instance.to.vpn.id.VpnInstance.class,
306                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
307                     .instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
308     }
309
310     static String getVpnInstanceFromVpnIdentifier(DataBroker broker, long vpnId) {
311         InstanceIdentifier<VpnIds> id = InstanceIdentifier.builder(VpnIdToVpnInstance.class)
312             .child(VpnIds.class, new VpnIdsKey(vpnId)).build();
313         Optional<VpnIds> vpnInstance = read(broker, LogicalDatastoreType.CONFIGURATION, id);
314         return vpnInstance.isPresent() ? vpnInstance.get().getVpnInstanceName() : null;
315     }
316
317     /*
318        getFlowRef() returns a string identfier for the SNAT flows using the router ID as the reference.
319     */
320     public static String getFlowRef(BigInteger dpnId, short tableId, long routerID, String ip) {
321         return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
322                 .FLOWID_SEPARATOR + routerID + NatConstants.FLOWID_SEPARATOR + ip;
323     }
324
325     public static String getFlowRef(BigInteger dpnId, short tableId, InetAddress destPrefix, long vpnId) {
326         return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
327                 .FLOWID_SEPARATOR + destPrefix.getHostAddress() + NatConstants.FLOWID_SEPARATOR + vpnId;
328     }
329
330     public static String getNaptFlowRef(BigInteger dpnId, short tableId, String routerID, String ip, int port) {
331         return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
332                 .FLOWID_SEPARATOR + routerID + NatConstants.FLOWID_SEPARATOR + ip + NatConstants.FLOWID_SEPARATOR
333                 + port;
334     }
335
336     static Uuid getNetworkIdFromRouterId(DataBroker broker, long routerId) {
337         String routerName = getRouterName(broker, routerId);
338         return getNetworkIdFromRouterName(broker, routerName);
339     }
340
341     static Uuid getNetworkIdFromRouterName(DataBroker broker, String routerName) {
342         if (routerName == null) {
343             LOG.error("getNetworkIdFromRouterName - empty routerName received");
344             return null;
345         }
346         InstanceIdentifier id = buildRouterIdentifier(routerName);
347         Optional<Routers> routerData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
348         if (routerData.isPresent()) {
349             return routerData.get().getNetworkId();
350         }
351         return null;
352     }
353
354     static InstanceIdentifier<Routers> buildRouterIdentifier(String routerId) {
355         InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class)
356             .child(Routers.class, new RoutersKey(routerId)).build();
357         return routerInstanceIndentifier;
358     }
359
360     private static InstanceIdentifier<RouterIds> buildRouterIdentifier(Long routerId) {
361         InstanceIdentifier<RouterIds> routerIds = InstanceIdentifier.builder(RouterIdName.class)
362             .child(RouterIds.class, new RouterIdsKey(routerId)).build();
363         return routerIds;
364     }
365
366     /**
367      * Return if SNAT is enabled for the given router.
368      *
369      * @param broker   The DataBroker
370      * @param routerId The router
371      * @return boolean true if enabled, otherwise false
372      */
373     static boolean isSnatEnabledForRouterId(DataBroker broker, String routerId) {
374         InstanceIdentifier id = buildRouterIdentifier(routerId);
375         Optional<Routers> routerData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
376         if (routerData.isPresent()) {
377             return routerData.get().isEnableSnat();
378         }
379         return false;
380     }
381
382     public static Uuid getVpnIdfromNetworkId(DataBroker broker, Uuid networkId) {
383         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
384         Optional<Networks> networkData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
385         if (networkData.isPresent()) {
386             return networkData.get().getVpnid();
387         }
388         return null;
389     }
390
391     public static ProviderTypes getProviderTypefromNetworkId(DataBroker broker, Uuid networkId) {
392         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
393         Optional<Networks> networkData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
394         if (networkData.isPresent() && networkData.get() != null) {
395             return networkData.get().getProviderNetworkType();
396         }
397         return null;
398     }
399
400     public static List<Uuid> getRouterIdsfromNetworkId(DataBroker broker, Uuid networkId) {
401         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
402         Optional<Networks> networkData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
403         return networkData.isPresent() ? networkData.get().getRouterIds() : Collections.emptyList();
404     }
405
406     static String getAssociatedExternalNetwork(DataBroker dataBroker, String routerId) {
407         InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
408         Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
409         if (routerData.isPresent()) {
410             Uuid networkId = routerData.get().getNetworkId();
411             if (networkId != null) {
412                 return networkId.getValue();
413             }
414         }
415         return null;
416     }
417
418     private static InstanceIdentifier<Networks> buildNetworkIdentifier(Uuid networkId) {
419         InstanceIdentifier<Networks> network = InstanceIdentifier.builder(ExternalNetworks.class)
420             .child(Networks.class, new NetworksKey(networkId)).build();
421         return network;
422     }
423
424     public static BigInteger getPrimaryNaptfromRouterId(DataBroker broker, Long routerId) {
425         // convert routerId to Name
426         String routerName = getRouterName(broker, routerId);
427         return getPrimaryNaptfromRouterName(broker, routerName);
428     }
429
430     public static BigInteger getPrimaryNaptfromRouterName(DataBroker broker, String routerName) {
431         if (routerName == null) {
432             LOG.error("getPrimaryNaptfromRouterName - empty routerName received");
433             return null;
434         }
435         InstanceIdentifier id = buildNaptSwitchIdentifier(routerName);
436         Optional<RouterToNaptSwitch> routerToNaptSwitchData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
437         if (routerToNaptSwitchData.isPresent()) {
438             RouterToNaptSwitch routerToNaptSwitchInstance = routerToNaptSwitchData.get();
439             return routerToNaptSwitchInstance.getPrimarySwitchId();
440         }
441         return null;
442     }
443
444     private static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchIdentifier(String routerId) {
445         InstanceIdentifier<RouterToNaptSwitch> rtrNaptSw = InstanceIdentifier.builder(NaptSwitches.class)
446             .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerId)).build();
447         return rtrNaptSw;
448     }
449
450     public static String getRouterName(DataBroker broker, Long routerId) {
451         InstanceIdentifier id = buildRouterIdentifier(routerId);
452         Optional<RouterIds> routerIdsData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
453         if (routerIdsData.isPresent()) {
454             RouterIds routerIdsInstance = routerIdsData.get();
455             return routerIdsInstance.getRouterName();
456         }
457         return null;
458     }
459
460     // TODO Clean up the exception handling
461     @SuppressWarnings("checkstyle:IllegalCatch")
462     public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
463                                                           InstanceIdentifier<T> path) {
464
465         ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
466
467         try {
468             return tx.read(datastoreType, path).get();
469         } catch (Exception e) {
470             throw new RuntimeException(e);
471         }
472     }
473
474     static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String vrfId) {
475         return InstanceIdentifier.builder(VpnInstanceOpData.class)
476             .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vrfId)).build();
477     }
478
479     public static long readVpnId(DataBroker broker, String vpnName) {
480         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
481             .instance.to.vpn.id.VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
482         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
483             .instance.to.vpn.id.VpnInstance> vpnInstance = read(broker, LogicalDatastoreType.CONFIGURATION, id);
484
485         long vpnId = NatConstants.INVALID_ID;
486         if (vpnInstance.isPresent()) {
487             vpnId = vpnInstance.get().getVpnId();
488         }
489
490         return vpnId;
491     }
492
493     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, BigInteger cookie, String flowId) {
494         return new FlowEntityBuilder()
495                 .setDpnId(dpnId)
496                 .setTableId(tableId)
497                 .setCookie(cookie)
498                 .setFlowId(flowId)
499                 .build();
500     }
501
502     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId) {
503         return new FlowEntityBuilder()
504                 .setDpnId(dpnId)
505                 .setTableId(tableId)
506                 .setFlowId(flowId)
507                 .build();
508     }
509
510     public static long getIpAddress(byte[] rawIpAddress) {
511         return ((rawIpAddress[0] & 0xFF) << 3 * 8) + ((rawIpAddress[1] & 0xFF) << 2 * 8)
512             + ((rawIpAddress[2] & 0xFF) << 1 * 8) + (rawIpAddress[3] & 0xFF) & 0xffffffffL;
513     }
514
515     public static String getEndpointIpAddressForDPN(DataBroker broker, BigInteger dpnId) {
516         String nextHopIp = null;
517         InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
518             InstanceIdentifier.builder(DpnEndpoints.class)
519                 .child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpnId)).build();
520         Optional<DPNTEPsInfo> tunnelInfo = read(broker, LogicalDatastoreType.CONFIGURATION, tunnelInfoId);
521         if (tunnelInfo.isPresent()) {
522             List<TunnelEndPoints> nexthopIpList = tunnelInfo.get().getTunnelEndPoints();
523             if (nexthopIpList != null && !nexthopIpList.isEmpty()) {
524                 nextHopIp = nexthopIpList.get(0).getIpAddress().getIpv4Address().getValue();
525             }
526         }
527         return nextHopIp;
528     }
529
530     public static String getVpnRd(DataBroker broker, String vpnName) {
531
532         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
533             .instance.to.vpn.id.VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
534         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
535             .instance.to.vpn.id.VpnInstance> vpnInstance = read(broker, LogicalDatastoreType.CONFIGURATION, id);
536
537         String rd = null;
538         if (vpnInstance.isPresent()) {
539             rd = vpnInstance.get().getVrfId();
540         }
541         return rd;
542     }
543
544     public static IpPortExternal getExternalIpPortMap(DataBroker broker, Long routerId, String internalIpAddress,
545                                                       String internalPort, NAPTEntryEvent.Protocol protocol) {
546         ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
547         InstanceIdentifier ipPortMapId =
548             buildIpToPortMapIdentifier(routerId, internalIpAddress, internalPort, protocolType);
549         Optional<IpPortMap> ipPortMapData = read(broker, LogicalDatastoreType.CONFIGURATION, ipPortMapId);
550         if (ipPortMapData.isPresent()) {
551             IpPortMap ipPortMapInstance = ipPortMapData.get();
552             return ipPortMapInstance.getIpPortExternal();
553         }
554         return null;
555     }
556
557     private static InstanceIdentifier<IpPortMap> buildIpToPortMapIdentifier(Long routerId, String internalIpAddress,
558                                                                             String internalPort,
559                                                                             ProtocolTypes protocolType) {
560         InstanceIdentifier<IpPortMap> ipPortMapId = InstanceIdentifier.builder(IntextIpPortMap.class)
561             .child(IpPortMapping.class, new IpPortMappingKey(routerId))
562             .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
563             .child(IpPortMap.class, new IpPortMapKey(internalIpAddress + ":" + internalPort)).build();
564         return ipPortMapId;
565     }
566
567     static boolean isVpnInterfaceConfigured(DataBroker broker, String interfaceName) {
568         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
569         return read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId).isPresent();
570     }
571
572     static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
573         return InstanceIdentifier.builder(VpnInterfaces.class)
574             .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build();
575     }
576
577     static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
578         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
579         return read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId).orNull();
580     }
581
582     public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
583         /*
584          * NodeConnectorId is of form 'openflow:dpnid:portnum'
585          */
586         String[] split = portId.getValue().split(OF_URI_SEPARATOR);
587         if (split == null || split.length != 3) {
588             return null;
589         }
590         return split[1];
591     }
592
593     public static BigInteger getDpIdFromInterface(
594         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
595             .state.Interface ifState) {
596         String lowerLayerIf = ifState.getLowerLayerIf().get(0);
597         NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
598         return new BigInteger(getDpnFromNodeConnectorId(nodeConnectorId));
599     }
600
601     public static String getRouterIdfromVpnInstance(DataBroker broker, String vpnName) {
602         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
603             .child(VpnMap.class, new VpnMapKey(new Uuid(vpnName))).build();
604         Optional<VpnMap> optionalVpnMap = read(broker, LogicalDatastoreType.CONFIGURATION,
605             vpnMapIdentifier);
606         if (optionalVpnMap.isPresent()) {
607             Uuid routerId = optionalVpnMap.get().getRouterId();
608             if (routerId != null) {
609                 return routerId.getValue();
610             }
611         }
612         return null;
613     }
614
615     static Uuid getVpnForRouter(DataBroker broker, String routerId) {
616         InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
617         Optional<VpnMaps> optionalVpnMaps = read(broker, LogicalDatastoreType.CONFIGURATION,
618             vpnMapsIdentifier);
619         if (optionalVpnMaps.isPresent() && optionalVpnMaps.get().getVpnMap() != null) {
620             List<VpnMap> allMaps = optionalVpnMaps.get().getVpnMap();
621             if (routerId != null) {
622                 for (VpnMap vpnMap : allMaps) {
623                     if (vpnMap.getRouterId() != null
624                         && routerId.equals(vpnMap.getRouterId().getValue())
625                         && !routerId.equals(vpnMap.getVpnId().getValue())) {
626                         return vpnMap.getVpnId();
627                     }
628                 }
629             }
630         }
631         return null;
632     }
633
634     static long getAssociatedVpn(DataBroker broker, String routerName) {
635         InstanceIdentifier<Routermapping> routerMappingId = NatUtil.getRouterVpnMappingId(routerName);
636         Optional<Routermapping> optRouterMapping =
637             NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, routerMappingId);
638         if (optRouterMapping.isPresent()) {
639             Routermapping routerMapping = optRouterMapping.get();
640             return routerMapping.getVpnId();
641         }
642         return NatConstants.INVALID_ID;
643     }
644
645     public static String getAssociatedVPN(DataBroker dataBroker, Uuid networkId, Logger log) {
646         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
647         if (vpnUuid == null) {
648             log.error("No VPN instance associated with ext network {}", networkId);
649             return null;
650         }
651         return vpnUuid.getValue();
652     }
653
654     // TODO Clean up the exception handling
655     @SuppressWarnings("checkstyle:IllegalCatch")
656     public static void addPrefixToBGP(DataBroker broker,
657                                       IBgpManager bgpManager,
658                                       IFibManager fibManager,
659                                       String vpnName,
660                                       String rd,
661                                       Uuid subnetId,
662                                       String prefix,
663                                       String nextHopIp,
664                                       String parentVpnRd,
665                                       String macAddress,
666                                       long label,
667                                       long l3vni,
668                                       Logger log, RouteOrigin origin, BigInteger dpId) {
669         try {
670             LOG.info("NAT Service : ADD: Adding Fib entry rd {} prefix {} nextHop {} label {}", rd,
671                     prefix, nextHopIp, label);
672             if (nextHopIp == null) {
673                 LOG.error("NAT Service : addPrefix prefix {} rd {} failed since nextHopIp cannot be null.", prefix, rd);
674                 return;
675             }
676
677             addPrefixToInterface(broker, getVpnId(broker, vpnName), null /*interfaceName*/,prefix, dpId, subnetId,
678                     /*isNatPrefix*/ true);
679             fibManager.addOrUpdateFibEntry(broker, rd, macAddress, prefix,
680                     Collections.singletonList(nextHopIp), VrfEntry.EncapType.Mplsgre, (int)label, l3vni /*l3vni*/,
681                     null /*gatewayMacAddress*/, parentVpnRd, origin, null /*writeTxn*/);
682             if (rd != null && !rd.equalsIgnoreCase(vpnName)) {
683             /* Publish to Bgp only if its an INTERNET VPN */
684                 bgpManager.advertisePrefix(rd, null /*macAddress*/, prefix, Collections.singletonList(nextHopIp),
685                         VrfEntry.EncapType.Mplsgre, (int) label, 0 /*l3vni*/, 0 /*l2vni*/,
686                         null /*gatewayMac*/);
687             }
688             LOG.info("NAT Service : ADD: Added Fib entry rd {} prefix {} nextHop {} label {}", rd,
689                     prefix, nextHopIp, label);
690         } catch (Exception e) {
691             LOG.error("NAT Service : Add prefix rd {} prefix {} nextHop {} label {} failed", rd,
692                     prefix, nextHopIp, label, e);
693         }
694     }
695
696     static void addPrefixToInterface(DataBroker broker, long vpnId, String interfaceName, String ipPrefix,
697                                      BigInteger dpId, Uuid subnetId, boolean isNatPrefix) {
698         InstanceIdentifier<Prefixes> prefixId = InstanceIdentifier.builder(PrefixToInterface.class)
699                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
700                         .VpnIds.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix
701                         .to._interface.VpnIdsKey(vpnId))
702                 .child(Prefixes.class, new PrefixesKey(ipPrefix)).build();
703         Prefixes prefix = new PrefixesBuilder().setDpnId(dpId).setIpAddress(ipPrefix).setVpnInterfaceName(interfaceName)
704                     .setNatPrefix(isNatPrefix).setSubnetId(subnetId).build();
705         try {
706             SingleTransactionDataBroker.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, prefixId, prefix);
707         } catch (TransactionCommitFailedException e) {
708             LOG.error("Failed to write prefxi-to-interface for {} vpn-id {} DPN {}", ipPrefix, vpnId, dpId);
709         }
710     }
711
712     static InstanceIdentifier<Ports> buildPortToIpMapIdentifier(String routerId, String portName) {
713         InstanceIdentifier<Ports> ipPortMapId = InstanceIdentifier.builder(FloatingIpInfo.class)
714             .child(RouterPorts.class, new RouterPortsKey(routerId)).child(Ports.class, new PortsKey(portName)).build();
715         return ipPortMapId;
716     }
717
718     static InstanceIdentifier<RouterPorts> buildRouterPortsIdentifier(String routerId) {
719         InstanceIdentifier<RouterPorts> routerInstanceIndentifier = InstanceIdentifier.builder(FloatingIpInfo.class)
720             .child(RouterPorts.class, new RouterPortsKey(routerId)).build();
721         return routerInstanceIndentifier;
722     }
723
724     public static List<Integer> getInternalIpPortListInfo(DataBroker dataBroker, Long routerId,
725                                                           String internalIpAddress, ProtocolTypes protocolType) {
726         Optional<IntIpProtoType> optionalIpProtoType = read(dataBroker, LogicalDatastoreType.CONFIGURATION,
727             buildSnatIntIpPortIdentifier(routerId, internalIpAddress, protocolType));
728         if (optionalIpProtoType.isPresent()) {
729             return optionalIpProtoType.get().getPorts();
730         }
731         return null;
732     }
733
734     public static InstanceIdentifier<IntIpProtoType> buildSnatIntIpPortIdentifier(Long routerId,
735                                                                                   String internalIpAddress,
736                                                                                   ProtocolTypes protocolType) {
737         InstanceIdentifier<IntIpProtoType> intIpProtocolTypeId =
738             InstanceIdentifier.builder(SnatintIpPortMap.class)
739                 .child(IntipPortMap.class, new IntipPortMapKey(routerId))
740                 .child(IpPort.class, new IpPortKey(internalIpAddress))
741                 .child(IntIpProtoType.class, new IntIpProtoTypeKey(protocolType)).build();
742         return intIpProtocolTypeId;
743     }
744
745     public static ProtocolTypes getProtocolType(NAPTEntryEvent.Protocol protocol) {
746         ProtocolTypes protocolType = ProtocolTypes.TCP.toString().equals(protocol.toString())
747             ? ProtocolTypes.TCP : ProtocolTypes.UDP;
748         return protocolType;
749     }
750
751     public static InstanceIdentifier<NaptSwitches> getNaptSwitchesIdentifier() {
752         return InstanceIdentifier.create(NaptSwitches.class);
753     }
754
755     public static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchRouterIdentifier(String routerId) {
756         return InstanceIdentifier.create(NaptSwitches.class)
757             .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerId));
758     }
759
760     public static String getGroupIdKey(String routerName) {
761         return "snatmiss." + routerName;
762     }
763
764     public static long createGroupId(String groupIdKey, IdManagerService idManager) {
765         AllocateIdInput getIdInput = new AllocateIdInputBuilder()
766             .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
767             .build();
768         try {
769             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
770             RpcResult<AllocateIdOutput> rpcResult = result.get();
771             return rpcResult.getResult().getIdValue();
772         } catch (NullPointerException | InterruptedException | ExecutionException e) {
773             LOG.trace("", e);
774         }
775         return 0;
776     }
777
778     // TODO Clean up the exception handling
779     @SuppressWarnings("checkstyle:IllegalCatch")
780     public static void removePrefixFromBGP(DataBroker broker, IBgpManager bgpManager, IFibManager fibManager,
781                                            String rd, String prefix, String vpnName, Logger log) {
782         try {
783             LOG.info("REMOVE: Removing Fib entry rd {} prefix {}", rd, prefix);
784             fibManager.removeFibEntry(broker, rd, prefix, null);
785             if (rd != null && !rd.equalsIgnoreCase(vpnName)) {
786                 bgpManager.withdrawPrefix(rd, prefix);
787             }
788             LOG.info("REMOVE: Removed Fib entry rd {} prefix {}", rd, prefix);
789         } catch (Exception e) {
790             log.error("Delete prefix for rd {} prefix {} vpnName {} failed", rd, prefix, vpnName, e);
791         }
792     }
793
794     public static IpPortMapping getIportMapping(DataBroker broker, long routerId) {
795         return read(broker, LogicalDatastoreType.CONFIGURATION, getIportMappingIdentifier(routerId)).orNull();
796     }
797
798     public static InstanceIdentifier<IpPortMapping> getIportMappingIdentifier(long routerId) {
799         return InstanceIdentifier.builder(IntextIpPortMap.class)
800             .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
801     }
802
803     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
804         .natservice.rev160111.intext.ip.map.IpMapping> getIpMappingBuilder(Long routerId) {
805         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111
806             .intext.ip.map.IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
807             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map
808                 .IpMapping.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111
809                 .intext.ip.map.IpMappingKey(routerId)).build();
810         return idBuilder;
811     }
812
813     public static List<String> getExternalIpsForRouter(DataBroker dataBroker, Long routerId) {
814         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext
815             .ip.map.IpMapping> ipMappingOptional =
816             read(dataBroker, LogicalDatastoreType.OPERATIONAL, getIpMappingBuilder(routerId));
817         List<String> externalIps = new ArrayList<>();
818         if (ipMappingOptional.isPresent()) {
819             List<IpMap> ipMaps = ipMappingOptional.get().getIpMap();
820             for (IpMap ipMap : ipMaps) {
821                 externalIps.add(ipMap.getExternalIp());
822             }
823             //remove duplicates
824             return new ArrayList<>(new HashSet<>(externalIps));
825         }
826         return null;
827     }
828
829     public static List<String> getExternalIpsForRouter(DataBroker dataBroker, String routerName) {
830         Routers routerData = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
831         if (routerData != null) {
832             return NatUtil.getIpsListFromExternalIps(routerData.getExternalIps());
833         }
834
835         return Collections.emptyList();
836     }
837
838     public static HashMap<String, Long> getExternalIpsLabelForRouter(DataBroker dataBroker, Long routerId) {
839         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext
840             .ip.map.IpMapping> ipMappingOptional =
841             read(dataBroker, LogicalDatastoreType.OPERATIONAL, getIpMappingBuilder(routerId));
842         HashMap<String, Long> externalIpsLabel = new HashMap<>();
843         if (ipMappingOptional.isPresent()) {
844             List<IpMap> ipMaps = ipMappingOptional.get().getIpMap();
845             for (IpMap ipMap : ipMaps) {
846                 externalIpsLabel.put(ipMap.getExternalIp(), ipMap.getLabel());
847             }
848             return externalIpsLabel;
849         }
850         return null;
851     }
852
853     public static String getLeastLoadedExternalIp(DataBroker dataBroker, long segmentId) {
854         String leastLoadedExternalIp = null;
855         InstanceIdentifier<ExternalCounters> id =
856             InstanceIdentifier.builder(ExternalIpsCounter.class)
857                 .child(ExternalCounters.class, new ExternalCountersKey(segmentId)).build();
858         Optional<ExternalCounters> externalCountersData =
859             MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
860         if (externalCountersData.isPresent()) {
861             ExternalCounters externalCounter = externalCountersData.get();
862             List<ExternalIpCounter> externalIpCounterList = externalCounter.getExternalIpCounter();
863             short countOfLstLoadExtIp = 32767;
864             for (ExternalIpCounter externalIpCounter : externalIpCounterList) {
865                 String curExternalIp = externalIpCounter.getExternalIp();
866                 short countOfCurExtIp = externalIpCounter.getCounter();
867                 if (countOfCurExtIp < countOfLstLoadExtIp) {
868                     countOfLstLoadExtIp = countOfCurExtIp;
869                     leastLoadedExternalIp = curExternalIp;
870                 }
871             }
872         }
873         return leastLoadedExternalIp;
874     }
875
876     public static String[] getSubnetIpAndPrefix(DataBroker dataBroker, Uuid subnetId) {
877         String subnetIP = getSubnetIp(dataBroker, subnetId);
878         if (subnetIP != null) {
879             return getSubnetIpAndPrefix(subnetIP);
880         }
881         return null;
882     }
883
884     public static String[] getSubnetIpAndPrefix(String subnetString) {
885         String[] subnetSplit = subnetString.split("/");
886         String subnetIp = subnetSplit[0];
887         String subnetPrefix = "0";
888         if (subnetSplit.length == 2) {
889             subnetPrefix = subnetSplit[1];
890         }
891         return new String[] {subnetIp, subnetPrefix};
892     }
893
894     public static String getSubnetIp(DataBroker dataBroker, Uuid subnetId) {
895         InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
896             .builder(Subnetmaps.class)
897             .child(Subnetmap.class, new SubnetmapKey(subnetId))
898             .build();
899         Optional<Subnetmap> removedSubnet = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
900         if (removedSubnet.isPresent()) {
901             Subnetmap subnetMapEntry = removedSubnet.get();
902             return subnetMapEntry.getSubnetIp();
903         }
904         return null;
905
906     }
907
908     public static String[] getExternalIpAndPrefix(String leastLoadedExtIpAddr) {
909         String[] leastLoadedExtIpAddrSplit = leastLoadedExtIpAddr.split("/");
910         String leastLoadedExtIp = leastLoadedExtIpAddrSplit[0];
911         String leastLoadedExtIpPrefix = String.valueOf(NatConstants.DEFAULT_PREFIX);
912         if (leastLoadedExtIpAddrSplit.length == 2) {
913             leastLoadedExtIpPrefix = leastLoadedExtIpAddrSplit[1];
914         }
915         return new String[] {leastLoadedExtIp, leastLoadedExtIpPrefix};
916     }
917
918     public static List<BigInteger> getDpnsForRouter(DataBroker dataBroker, String routerUuid) {
919         InstanceIdentifier id = InstanceIdentifier.builder(NeutronRouterDpns.class)
920             .child(RouterDpnList.class, new RouterDpnListKey(routerUuid)).build();
921         Optional<RouterDpnList> routerDpnListData = read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
922         List<BigInteger> dpns = new ArrayList<>();
923         if (routerDpnListData.isPresent()) {
924             List<DpnVpninterfacesList> dpnVpninterfacesList = routerDpnListData.get().getDpnVpninterfacesList();
925             for (DpnVpninterfacesList dpnVpnInterface : dpnVpninterfacesList) {
926                 dpns.add(dpnVpnInterface.getDpnId());
927             }
928             return dpns;
929         }
930         return null;
931     }
932
933     public static long getBgpVpnId(DataBroker dataBroker, String routerName) {
934         long bgpVpnId = NatConstants.INVALID_ID;
935         Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
936         if (bgpVpnUuid != null) {
937             bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
938         }
939         return bgpVpnId;
940     }
941
942     static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces
943         .RouterInterface getConfiguredRouterInterface(DataBroker broker, String interfaceName) {
944         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router
945             .interfaces.RouterInterface> optRouterInterface =
946             read(broker, LogicalDatastoreType.CONFIGURATION, NatUtil.getRouterInterfaceId(interfaceName));
947         if (optRouterInterface.isPresent()) {
948             return optRouterInterface.get();
949         }
950         return null;
951     }
952
953     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
954         .router.interfaces.RouterInterface> getRouterInterfaceId(String interfaceName) {
955         return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight
956             .netvirt.l3vpn.rev130911.RouterInterfaces.class)
957             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces
958                     .RouterInterface.class,
959                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces
960                     .RouterInterfaceKey(interfaceName)).build();
961     }
962
963     public static void addToNeutronRouterDpnsMap(DataBroker broker, String routerName, String interfaceName,
964             OdlInterfaceRpcService ifaceMgrRpcService, WriteTransaction writeOperTxn) {
965         BigInteger dpId = getDpnForInterface(ifaceMgrRpcService, interfaceName);
966         addToNeutronRouterDpnsMap(broker, routerName, interfaceName,  dpId, writeOperTxn);
967     }
968
969     public static void addToNeutronRouterDpnsMap(DataBroker broker, String routerName, String interfaceName,
970             BigInteger dpId , WriteTransaction writeOperTxn) {
971
972         if (dpId.equals(BigInteger.ZERO)) {
973             LOG.warn("NAT Service : Could not retrieve dp id for interface {} to handle router {} association model",
974                     interfaceName, routerName);
975             return;
976         }
977
978         LOG.debug("NAT Service : Adding the Router {} and DPN {} for the Interface {} in the "
979                 + "ODL-L3VPN : NeutronRouterDpn map",
980                 routerName, dpId, interfaceName);
981         InstanceIdentifier<DpnVpninterfacesList> dpnVpnInterfacesListIdentifier = getRouterDpnId(routerName, dpId);
982
983         Optional<DpnVpninterfacesList> optionalDpnVpninterfacesList = read(broker, LogicalDatastoreType
984                 .OPERATIONAL, dpnVpnInterfacesListIdentifier);
985         org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns
986             .router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces routerInterface =
987             new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(interfaceName))
988             .setInterface(interfaceName).build();
989         if (optionalDpnVpninterfacesList.isPresent()) {
990             LOG.debug("NAT Service : RouterDpnList already present for the Router {} and DPN {} for the "
991                     + "Interface {} in the ODL-L3VPN : NeutronRouterDpn map", routerName, dpId, interfaceName);
992             writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, dpnVpnInterfacesListIdentifier
993                     .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
994                             .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
995                             new RouterInterfacesKey(interfaceName)), routerInterface, true);
996         } else {
997             LOG.debug("NAT Service : Building new RouterDpnList for the Router {} and DPN {} for the "
998                     + "Interface {} in the ODL-L3VPN : NeutronRouterDpn map", routerName, dpId, interfaceName);
999             RouterDpnListBuilder routerDpnListBuilder = new RouterDpnListBuilder();
1000             routerDpnListBuilder.setRouterId(routerName);
1001             DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1002             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1003                 .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces> routerInterfaces = new ArrayList<>();
1004             routerInterfaces.add(routerInterface);
1005             dpnVpnList.setRouterInterfaces(routerInterfaces);
1006             routerDpnListBuilder.setDpnVpninterfacesList(Collections.singletonList(dpnVpnList.build()));
1007             writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1008                     getRouterId(routerName),
1009                     routerDpnListBuilder.build(), true);
1010         }
1011     }
1012
1013
1014     public static void addToDpnRoutersMap(DataBroker broker, String routerName, String interfaceName,
1015             OdlInterfaceRpcService ifaceMgrRpcService, WriteTransaction writeOperTxn) {
1016         BigInteger dpId = getDpnForInterface(ifaceMgrRpcService, interfaceName);
1017         addToDpnRoutersMap(broker, routerName, interfaceName, dpId, writeOperTxn);
1018     }
1019
1020     public static void addToDpnRoutersMap(DataBroker broker, String routerName, String interfaceName,
1021             BigInteger dpId, WriteTransaction writeOperTxn) {
1022         if (dpId.equals(BigInteger.ZERO)) {
1023             LOG.warn("NAT Service : Could not retrieve dp id for interface {} to handle router {} association model",
1024                     interfaceName, routerName);
1025             return;
1026         }
1027
1028         LOG.debug("NAT Service : Adding the DPN {} and router {} for the Interface {} in the ODL-L3VPN : "
1029                 + "DPNRouters map",
1030                 dpId, routerName, interfaceName);
1031         InstanceIdentifier<DpnRoutersList> dpnRoutersListIdentifier = getDpnRoutersId(dpId);
1032
1033         Optional<DpnRoutersList> optionalDpnRoutersList = read(broker, LogicalDatastoreType.OPERATIONAL,
1034                 dpnRoutersListIdentifier);
1035
1036         if (optionalDpnRoutersList.isPresent()) {
1037             RoutersList routersList = new RoutersListBuilder().setKey(new RoutersListKey(routerName))
1038                     .setRouter(routerName).build();
1039             List<RoutersList> routersListFromDs = optionalDpnRoutersList.get().getRoutersList();
1040             if (!routersListFromDs.contains(routersList)) {
1041                 LOG.debug("NAT Service : Router {} not present for the DPN {}"
1042                         + " in the ODL-L3VPN : DPNRouters map", routerName, dpId);
1043                 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1044                         dpnRoutersListIdentifier
1045                         .child(RoutersList.class, new RoutersListKey(routerName)), routersList, true);
1046             } else {
1047                 LOG.debug("NAT Service : Router {} already mapped to the DPN {} in the ODL-L3VPN : DPNRouters map",
1048                         routerName, dpId);
1049             }
1050         } else {
1051             LOG.debug("NAT Service : Building new DPNRoutersList for the Router {} present in the DPN {} "
1052                     + "ODL-L3VPN : DPNRouters map", routerName, dpId);
1053             DpnRoutersListBuilder dpnRoutersListBuilder = new DpnRoutersListBuilder();
1054             dpnRoutersListBuilder.setDpnId(dpId);
1055             RoutersListBuilder routersListBuilder = new RoutersListBuilder();
1056             routersListBuilder.setRouter(routerName);
1057             dpnRoutersListBuilder.setRoutersList(Collections.singletonList(routersListBuilder.build()));
1058             writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1059                     getDpnRoutersId(dpId),
1060                     dpnRoutersListBuilder.build(), true);
1061         }
1062     }
1063
1064
1065     public static void removeFromNeutronRouterDpnsMap(DataBroker broker, String routerName, String interfaceName,
1066                                                BigInteger dpId, WriteTransaction writeOperTxn) {
1067         if (dpId.equals(BigInteger.ZERO)) {
1068             LOG.warn("NAT Service : Could not retrieve dp id for interface {} to handle router {} dissociation model",
1069                 interfaceName, routerName);
1070             return;
1071         }
1072         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1073         Optional<DpnVpninterfacesList> optionalRouterDpnList = NatUtil.read(broker, LogicalDatastoreType
1074             .OPERATIONAL, routerDpnListIdentifier);
1075         if (optionalRouterDpnList.isPresent()) {
1076             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1077                 .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces> routerInterfaces =
1078                 optionalRouterDpnList.get().getRouterInterfaces();
1079             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1080                 .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces routerInterface =
1081                 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(interfaceName))
1082                     .setInterface(interfaceName).build();
1083             if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1084                 if (routerInterfaces.isEmpty()) {
1085                     writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1086                 } else {
1087                     writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1088                         org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1089                             .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
1090                         new RouterInterfacesKey(interfaceName)));
1091                 }
1092             }
1093         }
1094     }
1095
1096     public static void removeFromNeutronRouterDpnsMap(DataBroker broker, String routerName,
1097                                                BigInteger dpId, WriteTransaction writeOperTxn) {
1098         if (dpId.equals(BigInteger.ZERO)) {
1099             LOG.warn("NAT Service : DPN ID is invalid for the router {} ", routerName);
1100             return;
1101         }
1102
1103         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1104         Optional<DpnVpninterfacesList> optionalRouterDpnList = NatUtil.read(broker, LogicalDatastoreType
1105             .OPERATIONAL, routerDpnListIdentifier);
1106         if (optionalRouterDpnList.isPresent()) {
1107             LOG.debug("NAT Service : Removing the dpn-vpninterfaces-list from the odl-l3vpn:neutron-router-dpns model "
1108                 + "for the router {}", routerName);
1109             writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1110         } else {
1111             LOG.debug("NAT Service : dpn-vpninterfaces-list does not exist in the odl-l3vpn:neutron-router-dpns model "
1112                 + "for the router {}", routerName);
1113         }
1114     }
1115
1116     public static void removeFromNeutronRouterDpnsMap(DataBroker broker, String routerName, String vpnInterfaceName,
1117                                                OdlInterfaceRpcService ifaceMgrRpcService,
1118                                                WriteTransaction writeOperTxn) {
1119         BigInteger dpId = getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1120         if (dpId.equals(BigInteger.ZERO)) {
1121             LOG.warn("NAT Service : Could not retrieve dp id for interface {} to handle router {} dissociation model",
1122                 vpnInterfaceName, routerName);
1123             return;
1124         }
1125         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1126         Optional<DpnVpninterfacesList> optionalRouterDpnList = read(broker, LogicalDatastoreType
1127             .OPERATIONAL, routerDpnListIdentifier);
1128         if (optionalRouterDpnList.isPresent()) {
1129             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns
1130                 .router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces> routerInterfaces =
1131                 optionalRouterDpnList.get().getRouterInterfaces();
1132             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn
1133                 .list.dpn.vpninterfaces.list.RouterInterfaces routerInterface =
1134                 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName))
1135                     .setInterface(vpnInterfaceName).build();
1136
1137             if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1138                 if (routerInterfaces.isEmpty()) {
1139                     if (writeOperTxn != null) {
1140                         writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1141                     } else {
1142                         MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1143                     }
1144                 } else {
1145                     if (writeOperTxn != null) {
1146                         writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1147                             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1148                                 .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
1149                             new RouterInterfacesKey(vpnInterfaceName)));
1150                     } else {
1151                         MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1152                             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron
1153                                 .router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
1154                             new RouterInterfacesKey(vpnInterfaceName)));
1155                     }
1156                 }
1157             }
1158         }
1159     }
1160
1161     public static void removeFromDpnRoutersMap(DataBroker broker, String routerName, String vpnInterfaceName,
1162                                         OdlInterfaceRpcService ifaceMgrRpcService, WriteTransaction writeOperTxn) {
1163         BigInteger dpId = getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1164         if (dpId.equals(BigInteger.ZERO)) {
1165             LOG.warn("NAT Service : removeFromDpnRoutersMap() : Could not retrieve DPN ID for interface {} "
1166                     + "to handle router {} dissociation model",
1167                 vpnInterfaceName, routerName);
1168             return;
1169         }
1170         removeFromDpnRoutersMap(broker, routerName, vpnInterfaceName, dpId, ifaceMgrRpcService, writeOperTxn);
1171     }
1172
1173     static void removeFromDpnRoutersMap(DataBroker broker, String routerName, String vpnInterfaceName,
1174                                         BigInteger curDpnId,
1175                                         OdlInterfaceRpcService ifaceMgrRpcService, WriteTransaction writeOperTxn) {
1176         /*
1177             1) Get the DpnRoutersList for the DPN.
1178             2) Get the RoutersList identifier for the DPN and router.
1179             3) Get the VPN interfaces for the router (routerList) through which it is connected to the DPN.
1180             4) If the removed VPN interface is the only interface through which the router is connected to the DPN,
1181              then remove RouterList.
1182          */
1183
1184         LOG.debug("NAT Service : removeFromDpnRoutersMap() : Removing the DPN {} and router {} for the Interface {}"
1185             + " in the ODL-L3VPN : DPNRouters map", curDpnId, routerName, vpnInterfaceName);
1186
1187         //Get the dpn-routers-list instance for the current DPN.
1188         InstanceIdentifier<DpnRoutersList> dpnRoutersListIdentifier = getDpnRoutersId(curDpnId);
1189         Optional<DpnRoutersList> dpnRoutersListData = read(broker, LogicalDatastoreType.OPERATIONAL,
1190             dpnRoutersListIdentifier);
1191
1192         if (dpnRoutersListData == null || !dpnRoutersListData.isPresent()) {
1193             LOG.debug("NAT Service : dpn-routers-list is not present for DPN {} in the ODL-L3VPN:dpn-routers model",
1194                 curDpnId);
1195             return;
1196         }
1197
1198         //Get the routers-list instance for the router on the current DPN only
1199         InstanceIdentifier<RoutersList> routersListIdentifier = getRoutersList(curDpnId, routerName);
1200         Optional<RoutersList> routersListData = read(broker, LogicalDatastoreType.OPERATIONAL, routersListIdentifier);
1201
1202         if (routersListData == null || !routersListData.isPresent()) {
1203             LOG.debug("NAT Service : routers-list is not present for the DPN {} in the ODL-L3VPN:dpn-routers model",
1204                 curDpnId);
1205             return;
1206         }
1207
1208         LOG.debug("NAT Service : Get the interfaces for the router {} from the NeutronVPN - router-interfaces-map",
1209             routerName);
1210         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router
1211             .interfaces.map.RouterInterfaces> routerInterfacesId = getRoutersInterfacesIdentifier(routerName);
1212         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map
1213             .RouterInterfaces> routerInterfacesData = read(broker, LogicalDatastoreType.CONFIGURATION,
1214             routerInterfacesId);
1215
1216         if (routerInterfacesData == null || !routerInterfacesData.isPresent()) {
1217             LOG.debug("NAT Service : Unable to get the routers list for the DPN {}. Possibly all subnets removed"
1218                     + " from router {} OR Router {} has been deleted. Hence DPN router model WILL be cleared ",
1219                 curDpnId, routerName, routerName);
1220             writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routersListIdentifier);
1221             return;
1222         }
1223
1224         //Get the VM interfaces for the router on the current DPN only.
1225         List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces
1226             .map.router.interfaces.Interfaces> vmInterfaces = routerInterfacesData.get().getInterfaces();
1227         if (vmInterfaces == null) {
1228             LOG.debug("NAT Service : VM interfaces are not present for the router {} in the "
1229                 + "NeutronVPN - router-interfaces-map", routerName);
1230             return;
1231         }
1232
1233         // If the removed VPN interface is the only interface through which the router is connected to the DPN,
1234         // then remove RouterList.
1235         for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map
1236                  .router.interfaces.Interfaces vmInterface : vmInterfaces) {
1237             String vmInterfaceName = vmInterface.getInterfaceId();
1238             BigInteger vmDpnId = getDpnForInterface(ifaceMgrRpcService, vmInterfaceName);
1239             if (vmDpnId.equals(BigInteger.ZERO) || !vmDpnId.equals(curDpnId)) {
1240                 LOG.debug("NAT Service : DPN ID {} for the removed interface {} is not the same as that of "
1241                         + "the DPN ID for the checked interface {} ",
1242                     curDpnId, vpnInterfaceName, vmDpnId, vmInterfaceName);
1243                 continue;
1244             }
1245             if (!vmInterfaceName.equalsIgnoreCase(vpnInterfaceName)) {
1246                 LOG.debug("NAT Service : Router {} is present in the DPN {} through the other interface {} "
1247                     + "Hence DPN router model WOULD NOT be cleared", routerName, curDpnId, vmInterfaceName);
1248                 return;
1249             }
1250         }
1251         LOG.debug("NAT Service : Router {} is present in the DPN {} only through the interface {} "
1252             + "Hence DPN router model WILL be cleared. Possibly last VM for the router "
1253             + "deleted in the DPN", routerName, curDpnId, vpnInterfaceName);
1254         writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routersListIdentifier);
1255     }
1256
1257     private static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
1258         .rev150602.router.interfaces.map.RouterInterfaces> getRoutersInterfacesIdentifier(String routerName) {
1259         return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
1260             .rev150602.RouterInterfacesMap.class)
1261             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router
1262                     .interfaces.map.RouterInterfaces.class,
1263                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router
1264                     .interfaces.map.RouterInterfacesKey(new Uuid(routerName))).build();
1265     }
1266
1267     private static InstanceIdentifier<RoutersList> getRoutersList(BigInteger dpnId, String routerName) {
1268         return InstanceIdentifier.builder(DpnRouters.class)
1269             .child(DpnRoutersList.class, new DpnRoutersListKey(dpnId))
1270             .child(RoutersList.class, new RoutersListKey(routerName)).build();
1271     }
1272
1273     public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
1274         BigInteger nodeId = BigInteger.ZERO;
1275         try {
1276             GetDpidFromInterfaceInput
1277                 dpIdInput =
1278                 new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
1279             Future<RpcResult<GetDpidFromInterfaceOutput>>
1280                 dpIdOutput =
1281                 interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
1282             RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
1283             if (dpIdResult.isSuccessful()) {
1284                 nodeId = dpIdResult.getResult().getDpid();
1285             } else {
1286                 LOG.error("NAT Service : Could not retrieve DPN Id for interface {}", ifName);
1287             }
1288         } catch (NullPointerException | InterruptedException | ExecutionException e) {
1289             LOG.error("NAT Service : Exception when getting dpn for interface {}", ifName, e);
1290         }
1291         return nodeId;
1292     }
1293
1294     public static List<ActionInfo> getEgressActionsForInterface(OdlInterfaceRpcService interfaceManager, String ifName,
1295                                                                 Long tunnelKey) {
1296         return getEgressActionsForInterface(interfaceManager, ifName, tunnelKey, 0);
1297     }
1298
1299     public static List<ActionInfo> getEgressActionsForInterface(OdlInterfaceRpcService interfaceManager, String ifName,
1300                                                                 Long tunnelKey, int pos) {
1301         LOG.debug("NAT Service : getEgressActionsForInterface called for interface {}", ifName);
1302         GetEgressActionsForInterfaceInputBuilder egressActionsBuilder = new GetEgressActionsForInterfaceInputBuilder()
1303             .setIntfName(ifName);
1304         if (tunnelKey != null) {
1305             egressActionsBuilder.setTunnelKey(tunnelKey);
1306         }
1307
1308         List<ActionInfo> listActionInfo = new ArrayList<>();
1309         try {
1310             Future<RpcResult<GetEgressActionsForInterfaceOutput>> result = interfaceManager
1311                 .getEgressActionsForInterface(egressActionsBuilder.build());
1312             RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
1313             if (!rpcResult.isSuccessful()) {
1314                 LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName,
1315                     rpcResult.getErrors());
1316             } else {
1317                 List<Action> actions = rpcResult.getResult().getAction();
1318                 for (Action action : actions) {
1319                     org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action
1320                         actionClass = action.getAction();
1321                     if (actionClass instanceof OutputActionCase) {
1322                         listActionInfo.add(new ActionOutput(pos++,
1323                             ((OutputActionCase) actionClass).getOutputAction().getOutputNodeConnector()));
1324                     } else if (actionClass instanceof PushVlanActionCase) {
1325                         listActionInfo.add(new ActionPushVlan(pos++));
1326                     } else if (actionClass instanceof SetFieldCase) {
1327                         if (((SetFieldCase) actionClass).getSetField().getVlanMatch() != null) {
1328                             int vlanVid = ((SetFieldCase) actionClass).getSetField().getVlanMatch().getVlanId()
1329                                 .getVlanId().getValue();
1330                             listActionInfo.add(new ActionSetFieldVlanVid(pos++, vlanVid));
1331                         }
1332                     } else if (actionClass instanceof NxActionResubmitRpcAddGroupCase) {
1333                         Short tableId = ((NxActionResubmitRpcAddGroupCase) actionClass).getNxResubmit().getTable();
1334                         listActionInfo.add(new ActionNxResubmit(pos++, tableId));
1335                     } else if (actionClass instanceof NxActionRegLoadNodesNodeTableFlowApplyActionsCase) {
1336                         NxRegLoad nxRegLoad =
1337                             ((NxActionRegLoadNodesNodeTableFlowApplyActionsCase) actionClass).getNxRegLoad();
1338                         listActionInfo.add(new ActionRegLoad(pos++, NxmNxReg6.class, nxRegLoad.getDst().getStart(),
1339                             nxRegLoad.getDst().getEnd(), nxRegLoad.getValue().longValue()));
1340                     }
1341                 }
1342             }
1343         } catch (InterruptedException | ExecutionException e) {
1344             LOG.warn("Exception when egress actions for interface {}", ifName, e);
1345         }
1346         return listActionInfo;
1347     }
1348
1349     public static Port getNeutronPortForRouterGetewayIp(DataBroker broker, IpAddress targetIP) {
1350         return getNeutronPortForIp(broker, targetIP, NeutronConstants.DEVICE_OWNER_GATEWAY_INF);
1351     }
1352
1353     public static List<Port> getNeutronPorts(DataBroker broker) {
1354         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports>
1355             portsIdentifier = InstanceIdentifier.create(Neutron.class)
1356             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports.class);
1357         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports>
1358             portsOptional = read(broker, LogicalDatastoreType.CONFIGURATION, portsIdentifier);
1359
1360         if (!portsOptional.isPresent() || portsOptional.get().getPort() == null) {
1361             LOG.trace("No neutron ports found");
1362             return Collections.EMPTY_LIST;
1363         }
1364
1365         return portsOptional.get().getPort();
1366     }
1367
1368     public static Port getNeutronPortForIp(DataBroker broker,
1369                                            IpAddress targetIP, String deviceType) {
1370         List<Port> ports = getNeutronPorts(
1371             broker);
1372
1373         for (Port port : ports) {
1374             if (deviceType.equals(port.getDeviceOwner()) && port.getFixedIps() != null) {
1375                 for (FixedIps ip : port.getFixedIps()) {
1376                     if (Objects.equals(ip.getIpAddress(), targetIP)) {
1377                         return port;
1378                     }
1379                 }
1380             }
1381         }
1382
1383         return null;
1384     }
1385
1386     public static Uuid getSubnetIdForFloatingIp(Port port, IpAddress targetIP) {
1387         if (port == null) {
1388             return null;
1389         }
1390         for (FixedIps ip : port.getFixedIps()) {
1391             if (Objects.equals(ip.getIpAddress(), targetIP)) {
1392                 return ip.getSubnetId();
1393             }
1394         }
1395
1396         return null;
1397     }
1398
1399     public static Subnetmap getSubnetMap(DataBroker broker, Uuid subnetId) {
1400         InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier.builder(Subnetmaps.class)
1401             .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
1402         return read(broker, LogicalDatastoreType.CONFIGURATION, subnetmapId).orNull();
1403     }
1404
1405     public static List<Uuid> getSubnetIdsFromNetworkId(DataBroker broker, Uuid networkId) {
1406         InstanceIdentifier<NetworkMap> id = InstanceIdentifier.builder(NetworkMaps.class)
1407             .child(NetworkMap.class, new NetworkMapKey(networkId)).build();
1408         Optional<NetworkMap> optionalNetworkMap = read(broker, LogicalDatastoreType.CONFIGURATION, id);
1409         return optionalNetworkMap.isPresent() ? optionalNetworkMap.get().getSubnetIdList() : null;
1410     }
1411
1412     public static String getSubnetGwMac(DataBroker broker, Uuid subnetId, String vpnName) {
1413         if (subnetId == null) {
1414             return null;
1415         }
1416
1417         InstanceIdentifier<Subnet> subnetInst = InstanceIdentifier.create(Neutron.class).child(Subnets.class)
1418             .child(Subnet.class, new SubnetKey(subnetId));
1419         Optional<Subnet> subnetOpt = read(broker, LogicalDatastoreType.CONFIGURATION, subnetInst);
1420         if (!subnetOpt.isPresent()) {
1421             return null;
1422         }
1423
1424         IpAddress gatewayIp = subnetOpt.get().getGatewayIp();
1425         if (gatewayIp == null) {
1426             LOG.trace("No GW ip found for subnet {}", subnetId.getValue());
1427             return null;
1428         }
1429
1430         InstanceIdentifier<VpnPortipToPort> portIpInst = InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
1431             .child(VpnPortipToPort.class, new VpnPortipToPortKey(gatewayIp.getIpv4Address().getValue(), vpnName))
1432             .build();
1433         Optional<VpnPortipToPort> portIpToPortOpt = read(broker, LogicalDatastoreType.CONFIGURATION, portIpInst);
1434         if (portIpToPortOpt.isPresent()) {
1435             return portIpToPortOpt.get().getMacAddress();
1436         }
1437
1438         InstanceIdentifier<LearntVpnVipToPort> learntIpInst = InstanceIdentifier.builder(LearntVpnVipToPortData.class)
1439             .child(LearntVpnVipToPort.class, new LearntVpnVipToPortKey(gatewayIp.getIpv4Address().getValue(), vpnName))
1440             .build();
1441         Optional<LearntVpnVipToPort> learntIpToPortOpt = read(broker, LogicalDatastoreType.OPERATIONAL, learntIpInst);
1442         if (learntIpToPortOpt.isPresent()) {
1443             return learntIpToPortOpt.get().getMacAddress();
1444         }
1445
1446         LOG.error("No resolution was found to GW ip {} in subnet {}", gatewayIp, subnetId.getValue());
1447         return null;
1448     }
1449
1450     public static boolean isIPv6Subnet(String prefix) {
1451         return new IpPrefix(prefix.toCharArray()).getIpv6Prefix() != null;
1452     }
1453
1454     static InstanceIdentifier<DpnRoutersList> getDpnRoutersId(BigInteger dpnId) {
1455         return InstanceIdentifier.builder(DpnRouters.class)
1456             .child(DpnRoutersList.class, new DpnRoutersListKey(dpnId)).build();
1457     }
1458
1459     static InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1460         return InstanceIdentifier.builder(NeutronRouterDpns.class)
1461             .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1462             .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1463     }
1464
1465     static InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1466         return InstanceIdentifier.builder(NeutronRouterDpns.class)
1467             .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1468     }
1469
1470     protected static String getFloatingIpPortMacFromFloatingIpId(DataBroker broker, Uuid floatingIpId) {
1471         InstanceIdentifier id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
1472         Optional<FloatingIpIdToPortMapping> optFloatingIpIdToPortMapping = read(broker, LogicalDatastoreType
1473             .CONFIGURATION, id);
1474         if (optFloatingIpIdToPortMapping.isPresent()) {
1475             return optFloatingIpIdToPortMapping.get().getFloatingIpPortMacAddress();
1476         }
1477         return null;
1478     }
1479
1480     protected static Uuid getFloatingIpPortSubnetIdFromFloatingIpId(DataBroker broker, Uuid floatingIpId) {
1481         InstanceIdentifier id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
1482         Optional<FloatingIpIdToPortMapping> optFloatingIpIdToPortMapping = read(broker, LogicalDatastoreType
1483             .CONFIGURATION, id);
1484         if (optFloatingIpIdToPortMapping.isPresent()) {
1485             return optFloatingIpIdToPortMapping.get().getFloatingIpPortSubnetId();
1486         }
1487         return null;
1488     }
1489
1490     static InstanceIdentifier<FloatingIpIdToPortMapping> buildfloatingIpIdToPortMappingIdentifier(Uuid floatingIpId) {
1491         return InstanceIdentifier.builder(FloatingIpPortInfo.class).child(FloatingIpIdToPortMapping.class, new
1492             FloatingIpIdToPortMappingKey(floatingIpId)).build();
1493     }
1494
1495     static final FutureCallback<Void> DEFAULT_CALLBACK =
1496         new FutureCallback<Void>() {
1497             @Override
1498             public void onSuccess(Void result) {
1499                 LOG.debug("NAT Service : Success in Datastore operation");
1500             }
1501
1502             @Override
1503             public void onFailure(Throwable error) {
1504                 LOG.error("NAT Service : Error in Datastore operation", error);
1505             }
1506
1507             ;
1508         };
1509
1510     static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
1511                                               InstanceIdentifier<T> path) {
1512         delete(broker, datastoreType, path, DEFAULT_CALLBACK);
1513     }
1514
1515     static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
1516                                               InstanceIdentifier<T> path, FutureCallback<Void> callback) {
1517         WriteTransaction tx = broker.newWriteOnlyTransaction();
1518         tx.delete(datastoreType, path);
1519         Futures.addCallback(tx.submit(), callback);
1520     }
1521
1522     static Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
1523         InstanceIdentifier<Interface> ifStateId =
1524             buildStateInterfaceId(interfaceName);
1525         Optional<Interface> ifStateOptional = read(dataBroker, LogicalDatastoreType.OPERATIONAL, ifStateId);
1526         if (ifStateOptional.isPresent()) {
1527             return ifStateOptional.get();
1528         }
1529
1530         return null;
1531     }
1532
1533     static InstanceIdentifier<Interface> buildStateInterfaceId(String interfaceName) {
1534         InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
1535             InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
1536                 .interfaces.rev140508.InterfacesState.class)
1537                 .child(Interface.class,
1538                     new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
1539                         .interfaces.state.InterfaceKey(interfaceName));
1540         InstanceIdentifier<Interface> id = idBuilder.build();
1541         return id;
1542     }
1543
1544     public static Routers getRoutersFromConfigDS(DataBroker dataBroker, String routerName) {
1545         InstanceIdentifier<Routers> routerIdentifier = NatUtil.buildRouterIdentifier(routerName);
1546         Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerIdentifier);
1547         if (routerData.isPresent()) {
1548             return routerData.get();
1549         }
1550         return null;
1551     }
1552
1553     static void createRouterIdsConfigDS(DataBroker dataBroker, String routerName) {
1554         long routerId = NatUtil.getVpnId(dataBroker, routerName);
1555         if (routerId == NatConstants.INVALID_ID) {
1556             LOG.error("NAT Service : createRouterIdsConfigDS - invalid routerId for routerName {}", routerName);
1557             return;
1558         }
1559         RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(routerId))
1560             .setRouterId(routerId).setRouterName(routerName).build();
1561         MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, buildRouterIdentifier(routerId), rtrs);
1562     }
1563
1564     static FlowEntity buildDefaultNATFlowEntityForExternalSubnet(BigInteger dpId, long vpnId, String subnetId,
1565             IdManagerService idManager) {
1566         InetAddress defaultIP = null;
1567         try {
1568             defaultIP = InetAddress.getByName("0.0.0.0");
1569         } catch (UnknownHostException e) {
1570             LOG.error("NAT Service : UnknowHostException in buildDefNATFlowEntityForExternalSubnet. "
1571                 + "Failed to build FIB Table Flow for Default Route to NAT.");
1572             return null;
1573         }
1574
1575         List<MatchInfo> matches = new ArrayList<>();
1576         matches.add(MatchEthernetType.IPV4);
1577         //add match for vrfid
1578         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
1579
1580         List<InstructionInfo> instructions = new ArrayList<>();
1581         List<ActionInfo> actionsInfo = new ArrayList<>();
1582         long groupId = createGroupId(NatUtil.getGroupIdKey(subnetId), idManager);
1583         actionsInfo.add(new ActionGroup(groupId));
1584         String flowRef = getFlowRef(dpId, NwConstants.L3_FIB_TABLE, defaultIP, vpnId);
1585         instructions.add(new InstructionApplyActions(actionsInfo));
1586         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_FIB_TABLE, flowRef,
1587                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
1588                 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
1589         return flowEntity;
1590     }
1591
1592     static String getExtGwMacAddFromRouterId(DataBroker broker, long routerId) {
1593         String routerName = getRouterName(broker, routerId);
1594         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerName);
1595         Optional<Routers> routerData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
1596         if (routerData.isPresent()) {
1597             return routerData.get().getExtGwMacAddress();
1598         }
1599         return null;
1600     }
1601
1602     static InstanceIdentifier<Router> buildNeutronRouterIdentifier(Uuid routerUuid) {
1603         InstanceIdentifier<Router> routerInstanceIdentifier = InstanceIdentifier.create(Neutron.class)
1604              .child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers.class)
1605              .child(Router.class, new RouterKey(routerUuid));
1606         return routerInstanceIdentifier;
1607     }
1608
1609     public static String getNeutronRouterNamebyUuid(DataBroker broker, Uuid routerUuid) {
1610         InstanceIdentifier<Router> neutronRouterIdentifier = NatUtil.buildNeutronRouterIdentifier(routerUuid);
1611         Optional<Router> neutronRouterData = NatUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
1612                 neutronRouterIdentifier);
1613         if (neutronRouterData.isPresent()) {
1614             return neutronRouterData.get().getName();
1615         }
1616         return null;
1617     }
1618
1619     public static List<Ports> getFloatingIpPortsForRouter(DataBroker broker, Uuid routerUuid) {
1620
1621         InstanceIdentifier<RouterPorts> routerPortsIdentifier = getRouterPortsId(routerUuid.getValue());
1622         Optional<RouterPorts> routerPortsData = NatUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
1623                 routerPortsIdentifier);
1624         if (routerPortsData.isPresent()) {
1625             return routerPortsData.get().getPorts();
1626         }
1627         return null;
1628     }
1629
1630     public static List<Uuid> getRouterUuIdsForVpn(DataBroker broker, Uuid vpnUuid) {
1631         InstanceIdentifier<ExternalNetworks> externalNwIdentifier = InstanceIdentifier.create(ExternalNetworks.class);
1632         Optional<ExternalNetworks> externalNwData = NatUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
1633                 externalNwIdentifier);
1634         if (externalNwData.isPresent()) {
1635             for (Networks externalNw : externalNwData.get().getNetworks()) {
1636                 if (externalNw.getVpnid() != null && externalNw.getVpnid().equals(vpnUuid)) {
1637                     return externalNw.getRouterIds();
1638                 }
1639             }
1640         }
1641         return null;
1642     }
1643
1644     public static boolean isIpInSubnet(String ipAddress, String start, String end) {
1645
1646         try {
1647             long ipLo = ipToLong(InetAddress.getByName(start));
1648             long ipHi = ipToLong(InetAddress.getByName(end));
1649             long ipToTest = ipToLong(InetAddress.getByName(ipAddress));
1650             return ipToTest >= ipLo && ipToTest <= ipHi;
1651         } catch (UnknownHostException e) {
1652             LOG.error("NAT Service : isIpInSubnet failed for IP {}. Exception {}", ipAddress, e.getMessage());
1653             return false;
1654         }
1655     }
1656
1657     public static List<Uuid> getExternalSubnetIdsFromExternalIps(List<ExternalIps> externalIps) {
1658         if (externalIps == null) {
1659             return Collections.emptyList();
1660         }
1661
1662         Set<Uuid> subnetsSet = externalIps.stream().map(externalIp -> externalIp.getSubnetId())
1663                 .collect(Collectors.toSet());
1664         return new ArrayList<>(subnetsSet);
1665     }
1666
1667     public static List<Uuid> getExternalSubnetIdsForRouter(DataBroker dataBroker, String routerName) {
1668         if (routerName == null) {
1669             LOG.error("getExternalSubnetIdsForRouter - empty routerName received");
1670             return null;
1671         }
1672
1673         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerName);
1674         Optional<Routers> routerData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
1675         if (routerData.isPresent()) {
1676             return NatUtil.getExternalSubnetIdsFromExternalIps(routerData.get().getExternalIps());
1677         } else {
1678             LOG.warn("No external router data for router {}", routerName);
1679             return Collections.emptyList();
1680         }
1681     }
1682
1683     @Nonnull
1684     protected static Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
1685         .subnets.Subnets> getOptionalExternalSubnets(DataBroker dataBroker, Uuid subnetId) {
1686         if (subnetId == null) {
1687             LOG.warn("getOptionalExternalSubnets - null subnetId");
1688             return Optional.absent();
1689         }
1690
1691         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice
1692             .rev160111.external.subnets.Subnets> subnetsIdentifier =
1693                 InstanceIdentifier.builder(ExternalSubnets.class)
1694                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice
1695                         .rev160111.external.subnets.Subnets.class, new SubnetsKey(subnetId)).build();
1696         return read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetsIdentifier);
1697     }
1698
1699     protected static long getExternalSubnetVpnId(DataBroker dataBroker, Uuid subnetId) {
1700         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
1701             .subnets.Subnets> optionalExternalSubnets = NatUtil.getOptionalExternalSubnets(dataBroker,
1702                    subnetId);
1703         if (optionalExternalSubnets.isPresent()) {
1704             return NatUtil.getVpnId(dataBroker, subnetId.getValue());
1705         }
1706
1707         return NatConstants.INVALID_ID;
1708     }
1709
1710     protected static long getExternalSubnetVpnIdForRouterExternalIp(DataBroker dataBroker, String externalIpAddress,
1711             Routers router) {
1712         Uuid externalSubnetId = NatUtil.getExternalSubnetForRouterExternalIp(dataBroker, externalIpAddress, router);
1713         if (externalSubnetId != null) {
1714             return NatUtil.getExternalSubnetVpnId(dataBroker,externalSubnetId);
1715         }
1716
1717         return NatConstants.INVALID_ID;
1718     }
1719
1720     protected static Uuid getExternalSubnetForRouterExternalIp(DataBroker dataBroker, String externalIpAddress,
1721             Routers router) {
1722         externalIpAddress = validateAndAddNetworkMask(externalIpAddress);
1723         List<ExternalIps> externalIps = router.getExternalIps();
1724         for (ExternalIps extIp : externalIps) {
1725             String extIpString = validateAndAddNetworkMask(extIp.getIpAddress());
1726             if (extIpString.equals(externalIpAddress)) {
1727                 return extIp.getSubnetId();
1728             }
1729         }
1730
1731         return null;
1732     }
1733
1734     private static long ipToLong(InetAddress ip) {
1735         byte[] octets = ip.getAddress();
1736         long result = 0;
1737         for (byte octet : octets) {
1738             result <<= 8;
1739             result |= octet & 0xff;
1740         }
1741         return result;
1742     }
1743
1744     static List<String> getIpsListFromExternalIps(List<ExternalIps> externalIps) {
1745         if (externalIps == null) {
1746             return Collections.emptyList();
1747         }
1748
1749         return externalIps.stream().map(externalIp -> externalIp.getIpAddress()).collect(Collectors.toList());
1750     }
1751
1752     // elan-instances config container
1753     public static ElanInstance getElanInstanceByName(String elanInstanceName, DataBroker broker) {
1754         InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
1755         return read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orNull();
1756     }
1757
1758     public static InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
1759         return InstanceIdentifier.builder(ElanInstances.class)
1760                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
1761
1762     }
1763
1764     public static long getTunnelIdForNonNaptToNaptFlow(DataBroker dataBroker, IElanService elanManager,
1765             IdManagerService idManager, long routerId, String routerName) {
1766         if (elanManager.isOpenStackVniSemanticsEnforced()) {
1767             // Router VNI will be set as tun_id if OpenStackSemantics is enabled
1768             return NatOverVxlanUtil.getRouterVni(idManager, routerName, routerId).longValue();
1769         } else {
1770             return NatEvpnUtil.getTunnelIdForRouter(idManager, dataBroker, routerName, routerId);
1771         }
1772     }
1773
1774     public static void makePreDnatToSnatTableEntry(IMdsalApiManager mdsalManager, BigInteger naptDpnId,
1775             short tableId) {
1776         LOG.debug("NAT Service : Create Pre-DNAT table {} --> table {} flow on NAPT DpnId {} ",
1777                 NwConstants.PDNAT_TABLE, tableId, naptDpnId);
1778
1779         List<Instruction> preDnatToSnatInstructions = new ArrayList<>();
1780         preDnatToSnatInstructions.add(new InstructionGotoTable(tableId).buildInstruction(0));
1781         List<MatchInfo> matches = new ArrayList<>();
1782         matches.add(MatchEthernetType.IPV4);
1783         String flowRef = getFlowRefPreDnatToSnat(naptDpnId, NwConstants.PDNAT_TABLE, "PreDNATToSNAT");
1784         Flow preDnatToSnatTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.PDNAT_TABLE,flowRef,
1785                 5, flowRef, 0, 0,  NwConstants.COOKIE_DNAT_TABLE,
1786                 matches, preDnatToSnatInstructions);
1787
1788         mdsalManager.installFlow(naptDpnId, preDnatToSnatTableFlowEntity);
1789         LOG.debug("NAT Service : Successfully installed Pre-DNAT flow {} on NAPT DpnId {} ",
1790                 preDnatToSnatTableFlowEntity,  naptDpnId);
1791     }
1792
1793     public static void removePreDnatToSnatTableEntry(IMdsalApiManager mdsalManager, BigInteger naptDpnId) {
1794         LOG.debug("NAT Service : Remove Pre-DNAT table {} --> table {} flow on NAPT DpnId {} ",
1795                 NwConstants.PDNAT_TABLE, NwConstants.INBOUND_NAPT_TABLE, naptDpnId);
1796         String flowRef = getFlowRefPreDnatToSnat(naptDpnId, NwConstants.PDNAT_TABLE, "PreDNATToSNAT");
1797         Flow preDnatToSnatTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.PDNAT_TABLE,flowRef,
1798                 5, flowRef, 0, 0,  NwConstants.COOKIE_DNAT_TABLE, null, null);
1799         mdsalManager.removeFlow(naptDpnId, preDnatToSnatTableFlowEntity);
1800         LOG.debug("NAT Service : Successfully removed Pre-DNAT flow {} on NAPT DpnId = {}",
1801                 preDnatToSnatTableFlowEntity, naptDpnId);
1802     }
1803
1804     private static String getFlowRefPreDnatToSnat(BigInteger dpnId, short tableId, String uniqueId) {
1805         return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId
1806                 + NwConstants.FLOWID_SEPARATOR + uniqueId;
1807     }
1808
1809     public static Boolean isFloatingIpPresentForDpn(DataBroker dataBroker, BigInteger dpnId, String rd,
1810                                                     String vpnName, String externalIp,
1811                                                     Boolean isMoreThanOneFipCheckOnDpn) {
1812         InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
1813         Optional<VpnToDpnList> dpnInVpn = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
1814         if (dpnInVpn.isPresent()) {
1815             LOG.debug("vpn-to-dpn-list is not empty for vpnName {}, dpn id {}, rd {} and floatingIp {}",
1816                     vpnName, dpnId, rd, externalIp);
1817             List<IpAddresses> ipAddressList = dpnInVpn.get().getIpAddresses();
1818             if (ipAddressList.size() > 0) {
1819                 int floatingIpPresentCount = 0;
1820                 for (IpAddresses ipAddress: ipAddressList) {
1821                     if (!ipAddress.getIpAddress().equals(externalIp)
1822                             && IpAddresses.IpAddressSource.FloatingIP.equals(ipAddress.getIpAddressSource())) {
1823                         floatingIpPresentCount++;
1824                         //Add tunnel table check
1825                         if (isMoreThanOneFipCheckOnDpn && floatingIpPresentCount > 1) {
1826                             return Boolean.TRUE;
1827                         }
1828                         //Remove tunnel table check
1829                         if (!isMoreThanOneFipCheckOnDpn) {
1830                             return Boolean.TRUE;
1831                         }
1832                     }
1833                 }
1834             } else {
1835                 LOG.debug("vpn-to-dpn-list does not contain any floating IP for DPN {}", dpnId);
1836                 return Boolean.FALSE;
1837             }
1838         }
1839         return Boolean.FALSE;
1840     }
1841
1842     private static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
1843         return InstanceIdentifier.builder(VpnInstanceOpData.class)
1844                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd))
1845                 .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
1846     }
1847
1848     public static void createOrUpdateVpnToDpnList(DataBroker dataBroker, long vpnId, BigInteger dpnId, String intfName,
1849             String vpnName, WriteTransaction writeTxn) {
1850         String primaryRd = getPrimaryRd(dataBroker, vpnName);
1851         Boolean newDpnOnVpn = Boolean.FALSE;
1852
1853         synchronized (vpnName.intern()) {
1854             InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(primaryRd, dpnId);
1855             Optional<VpnToDpnList> dpnInVpn = read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
1856             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance
1857                 .op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnInterface = new VpnInterfacesBuilder()
1858                 .setInterfaceName(intfName).build();
1859
1860             if (dpnInVpn.isPresent()) {
1861                 VpnToDpnList vpnToDpnList = dpnInVpn.get();
1862                 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn
1863                     .instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = vpnToDpnList
1864                     .getVpnInterfaces();
1865                 if (vpnInterfaces == null) {
1866                     vpnInterfaces = new ArrayList<>();
1867                 }
1868                 vpnInterfaces.add(vpnInterface);
1869                 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
1870                 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
1871
1872                 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
1873                 /* If earlier state was inactive, it is considered new DPN coming back to the
1874                  * same VPN
1875                  */
1876                 if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
1877                     newDpnOnVpn = Boolean.TRUE;
1878                 }
1879             } else {
1880                 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn
1881                     .instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces>
1882                     vpnInterfaces = new ArrayList<>();
1883                 vpnInterfaces.add(vpnInterface);
1884                 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
1885                 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
1886
1887                 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
1888                 newDpnOnVpn = Boolean.TRUE;
1889             }
1890         }
1891     }
1892
1893     public static void removeOrUpdateVpnToDpnList(DataBroker dataBroker, long vpnId, BigInteger dpnId, String intfName,
1894             String vpnName, WriteTransaction writeTxn) {
1895         Boolean lastDpnOnVpn = Boolean.FALSE;
1896         String rd = getVpnRd(dataBroker, vpnName);
1897         synchronized (vpnName.intern()) {
1898             InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
1899             VpnToDpnList dpnInVpn = read(dataBroker, LogicalDatastoreType.OPERATIONAL, id).orNull();
1900             if (dpnInVpn == null) {
1901                 LOG.error("removeOrUpdateVpnToDpnList: Could not find DpnToVpn map for VPN=[name={} rd={} id={}]"
1902                     + " and dpnId={}", vpnName, rd, id, dpnId);
1903                 return;
1904             }
1905             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn
1906                 .instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.getVpnInterfaces();
1907             if (vpnInterfaces == null) {
1908                 LOG.error("Could not find vpnInterfaces for DpnInVpn map for VPN=[name={} rd={} id={}] and dpnId={}",
1909                          vpnName, rd, id, dpnId);
1910                 return;
1911             }
1912
1913             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn
1914                 .instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces currVpnInterface = new VpnInterfacesBuilder()
1915                 .setInterfaceName(intfName).build();
1916             if (vpnInterfaces.remove(currVpnInterface)) {
1917                 if (vpnInterfaces.isEmpty()) {
1918                     List<IpAddresses> ipAddresses = dpnInVpn.getIpAddresses();
1919                     VpnToDpnListBuilder dpnInVpnBuilder = new VpnToDpnListBuilder(dpnInVpn).setVpnInterfaces(null);
1920                     if (ipAddresses == null || ipAddresses.isEmpty()) {
1921                         dpnInVpnBuilder.setDpnState(VpnToDpnList.DpnState.Inactive);
1922                         lastDpnOnVpn = Boolean.TRUE;
1923                     } else {
1924                         LOG.warn("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}",
1925                                  vpnName, dpnId);
1926                     }
1927                     writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(), true);
1928
1929                 } else {
1930                     writeTxn.delete(LogicalDatastoreType.OPERATIONAL, id.child(org.opendaylight.yang.gen.v1.urn
1931                             .opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry
1932                             .vpn.to.dpn.list.VpnInterfaces.class, new VpnInterfacesKey(intfName)));
1933                 }
1934             }
1935         } // Ends synchronized block
1936
1937        /* if (lastDpnOnVpn) {
1938             LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
1939             fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd,
1940                 false  exited ));
1941         }*/
1942     }
1943
1944     public static String getPrimaryRd(DataBroker dataBroker, String vpnName) {
1945         InstanceIdentifier<VpnInstance> id  = getVpnInstanceIdentifier(vpnName);
1946         Optional<VpnInstance> vpnInstance = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
1947         if (vpnInstance.isPresent()) {
1948             return getPrimaryRd(vpnInstance.get());
1949         }
1950         return vpnName;
1951     }
1952
1953     public static String getPrimaryRd(VpnInstance vpnInstance) {
1954         List<String> rds = null;
1955         if (vpnInstance != null) {
1956             rds = getListOfRdsFromVpnInstance(vpnInstance);
1957         }
1958         return rds == null || rds.isEmpty() ? vpnInstance.getVpnInstanceName() : rds.get(0);
1959     }
1960
1961     public static InstanceIdentifier<VpnInstance> getVpnInstanceIdentifier(String vpnName) {
1962         return InstanceIdentifier.builder(VpnInstances.class)
1963             .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
1964     }
1965
1966     public static List<String> getListOfRdsFromVpnInstance(VpnInstance vpnInstance) {
1967         VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
1968         return vpnConfig.getRouteDistinguisher() != null ? new ArrayList<>(
1969                 vpnConfig.getRouteDistinguisher()) : new ArrayList<>();
1970     }
1971
1972     public static long getVpnIdFromExternalSubnet(DataBroker dataBroker, String routerName, String externalIpAddress) {
1973         if (routerName != null) {
1974             Routers extRouter = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
1975             if (extRouter != null) {
1976                 return getExternalSubnetVpnIdForRouterExternalIp(dataBroker, externalIpAddress, extRouter);
1977             }
1978         }
1979
1980         return NatConstants.INVALID_ID;
1981     }
1982
1983     public static void djcFlow(FlowEntity flowEntity, int addOrRemove, IMdsalApiManager mdsalManager) {
1984         DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1985         String jobKey = (flowEntity.getFlowName() != null) ? flowEntity.getFlowName() : flowEntity.getFlowId();
1986         dataStoreCoordinator.enqueueJob(jobKey, () -> {
1987             List<ListenableFuture<Void>> futures = new ArrayList<>();
1988             if (addOrRemove == NwConstants.ADD_FLOW) {
1989                 futures.add(mdsalManager.installFlow(flowEntity));
1990             } else {
1991                 futures.add(mdsalManager.removeFlow(flowEntity));
1992             }
1993             return futures;
1994         });
1995     }
1996
1997     public static String validateAndAddNetworkMask(String ipAddress) {
1998         return ipAddress.contains("/32") ? ipAddress : (ipAddress + "/32");
1999     }
2000 }