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