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