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