Scale-in/Scale-out for NAT.
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / NatUtil.java
1 /*
2  * Copyright © 2016, 2018 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 package org.opendaylight.netvirt.natservice.internal;
9
10 import static java.util.Collections.emptyList;
11 import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
12 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
13
14 import com.google.common.base.Optional;
15 import com.google.common.base.Preconditions;
16 import com.google.common.base.Splitter;
17 import com.google.common.base.Strings;
18 import com.google.common.collect.Iterables;
19 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
20 import java.math.BigInteger;
21 import java.net.InetAddress;
22 import java.net.UnknownHostException;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Objects;
31 import java.util.Set;
32 import java.util.concurrent.ExecutionException;
33 import java.util.concurrent.Future;
34 import java.util.concurrent.locks.ReentrantLock;
35 import java.util.stream.Collectors;
36 import org.apache.commons.net.util.SubnetUtils;
37 import org.eclipse.jdt.annotation.NonNull;
38 import org.eclipse.jdt.annotation.Nullable;
39 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
40 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
41 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
42 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
43 import org.opendaylight.controller.sal.common.util.Arguments;
44 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
45 import org.opendaylight.genius.infra.Datastore.Configuration;
46 import org.opendaylight.genius.infra.Datastore.Operational;
47 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
48 import org.opendaylight.genius.infra.TypedReadTransaction;
49 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
50 import org.opendaylight.genius.infra.TypedWriteTransaction;
51 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
52 import org.opendaylight.genius.mdsalutil.ActionInfo;
53 import org.opendaylight.genius.mdsalutil.BucketInfo;
54 import org.opendaylight.genius.mdsalutil.FlowEntity;
55 import org.opendaylight.genius.mdsalutil.FlowEntityBuilder;
56 import org.opendaylight.genius.mdsalutil.GroupEntity;
57 import org.opendaylight.genius.mdsalutil.InstructionInfo;
58 import org.opendaylight.genius.mdsalutil.MDSALUtil;
59 import org.opendaylight.genius.mdsalutil.MatchInfo;
60 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
61 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
62 import org.opendaylight.genius.mdsalutil.NwConstants;
63 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
64 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
65 import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
66 import org.opendaylight.genius.mdsalutil.actions.ActionPushVlan;
67 import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
68 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldVlanVid;
69 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
70 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
71 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
72 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
73 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
74 import org.opendaylight.genius.utils.JvmGlobalLocks;
75 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
76 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
77 import org.opendaylight.netvirt.elanmanager.api.IElanService;
78 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
79 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
80 import org.opendaylight.netvirt.natservice.ha.NatDataUtil;
81 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
82 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
83 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
84 import org.opendaylight.serviceutils.upgrade.UpgradeState;
85 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
86 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
87 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
88 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
89 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
90 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
91 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
92 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
93 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder;
94 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
95 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCase;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntry;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.bridge.ref.info.BridgeRefEntryKey;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInputBuilder;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInputBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesListKey;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesBuilder;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesKey;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.DpnRouters;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.LearntVpnVipToPortData;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PrefixToInterface;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInterfaceOpData;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersList;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersListBuilder;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersListKey;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersList;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersListBuilder;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersListKey;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPortKey;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
178 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesBuilder;
179 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey;
180 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
181 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
182 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
183 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsKey;
184 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
185 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
186 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
187 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
188 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;
189 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
190 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
191 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
192 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalSubnets;
193 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
194 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpPortInfo;
195 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpMap;
196 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
197 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
198 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
199 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
200 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterIdName;
201 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterToVpnMapping;
202 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.SnatintIpPortMap;
203 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
204 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
205 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
206 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
207 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCountersKey;
208 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
209 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
210 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
211 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.SubnetsKey;
212 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
213 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPortsKey;
214 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
215 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.PortsKey;
216 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
217 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMapKey;
218 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMapping;
219 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingKey;
220 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
221 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
222 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
223 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
224 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolTypeKey;
225 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
226 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapKey;
227 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;
228 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
229 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
230 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIds;
231 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsBuilder;
232 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsKey;
233 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.to.vpn.mapping.Routermapping;
234 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.to.vpn.mapping.RoutermappingKey;
235 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMap;
236 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMapKey;
237 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
238 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPortKey;
239 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
240 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeKey;
241 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInputBuilder;
242 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
243 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkMaps;
244 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
245 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
246 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
247 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
248 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
249 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey;
250 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
251 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
252 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
253 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
254 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
255 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
256 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
257 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.RouterKey;
258 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
259 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
260 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;
261 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
262 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
263 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
264 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
265 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
266 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionResubmitRpcAddGroupCase;
267 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;
268 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
269 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
270 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
271 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
272 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
273 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
274 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
275 import org.opendaylight.yangtools.yang.common.RpcResult;
276 import org.slf4j.Logger;
277 import org.slf4j.LoggerFactory;
278
279 public final class NatUtil {
280
281     private static String OF_URI_SEPARATOR = ":";
282     private static final Logger LOG = LoggerFactory.getLogger(NatUtil.class);
283     private static final String OTHER_CONFIG_PARAMETERS_DELIMITER = ",";
284     private static final String OTHER_CONFIG_KEY_VALUE_DELIMITER = ":";
285     private static final String PROVIDER_MAPPINGS = "provider_mappings";
286
287     private NatUtil() {
288
289     }
290
291     /*
292      getCookieSnatFlow() computes and returns a unique cookie value for the NAT flows using the router ID as the
293       reference value.
294      */
295     public static BigInteger getCookieSnatFlow(long routerId) {
296         return NatConstants.COOKIE_NAPT_BASE.add(new BigInteger("0110000", 16)).add(
297             BigInteger.valueOf(routerId));
298     }
299
300     /*
301       getCookieNaptFlow() computes and returns a unique cookie value for the NAPT flows using the router ID as the
302        reference value.
303     */
304     public static BigInteger getCookieNaptFlow(long routerId) {
305         return NatConstants.COOKIE_NAPT_BASE.add(new BigInteger("0111000", 16)).add(
306             BigInteger.valueOf(routerId));
307     }
308
309     /*
310         getVpnId() returns the VPN ID from the VPN name
311      */
312     public static long getVpnId(DataBroker broker, @Nullable String vpnName) {
313         if (vpnName == null) {
314             return NatConstants.INVALID_ID;
315         }
316
317         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
318             .instance.to.vpn.id.VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
319         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
320                 .instance.to.vpn.id.VpnInstance> vpnInstance =
321                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
322                         LogicalDatastoreType.CONFIGURATION, id);
323
324         long vpnId = NatConstants.INVALID_ID;
325         if (vpnInstance.isPresent()) {
326             Long vpnIdAsLong = vpnInstance.get().getVpnId();
327             if (vpnIdAsLong != null) {
328                 vpnId = vpnIdAsLong;
329             }
330         }
331         return vpnId;
332     }
333
334     public static long getVpnId(TypedReadTransaction<Configuration> confTx, String vpnName) {
335         if (vpnName == null) {
336             return NatConstants.INVALID_ID;
337         }
338
339         try {
340             return confTx.read(getVpnInstanceToVpnIdIdentifier(vpnName)).get().toJavaUtil().map(
341                 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
342                     .VpnInstance::getVpnId).orElse(Long.valueOf(NatConstants.INVALID_ID));
343         } catch (InterruptedException | ExecutionException e) {
344             LOG.error("Error retrieving VPN id for {}", vpnName, e);
345         }
346
347         return NatConstants.INVALID_ID;
348     }
349
350     public static Long getNetworkVpnIdFromRouterId(DataBroker broker, long routerId) {
351         //Get the external network ID from the ExternalRouter model
352         Uuid networkId = NatUtil.getNetworkIdFromRouterId(broker, routerId);
353         if (networkId == null) {
354             LOG.error("getNetworkVpnIdFromRouterId : networkId is null");
355             return Long.valueOf(NatConstants.INVALID_ID);
356         }
357
358         //Get the VPN ID from the ExternalNetworks model
359         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(broker, networkId);
360         if (vpnUuid == null) {
361             LOG.error("getNetworkVpnIdFromRouterId : vpnUuid is null");
362             return Long.valueOf(NatConstants.INVALID_ID);
363         }
364         Long vpnId = NatUtil.getVpnId(broker, vpnUuid.getValue());
365         return vpnId;
366     }
367
368     public static Boolean validateIsIntefacePartofRouter(DataBroker broker, String routerName, String interfaceName) {
369         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces
370             .map.router.interfaces.Interfaces> vmInterfaceIdentifier = getRoutersInterfacesIdentifier(routerName,
371             interfaceName);
372
373         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces
374             .map.router.interfaces.Interfaces> routerInterfacesData;
375         try {
376             routerInterfacesData = SingleTransactionDataBroker.syncReadOptional(broker,
377                 LogicalDatastoreType.CONFIGURATION, vmInterfaceIdentifier);
378         } catch (ReadFailedException e) {
379             LOG.error("Read Failed Exception While read RouterInterface data for router {}", routerName, e);
380             routerInterfacesData = Optional.absent();
381         }
382         if (routerInterfacesData.isPresent()) {
383             return Boolean.TRUE;
384         } else {
385             return Boolean.FALSE;
386         }
387     }
388
389     private static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
390         .rev150602.router.interfaces
391         .map.router.interfaces.Interfaces> getRoutersInterfacesIdentifier(String routerName, String interfaceName) {
392         return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
393             .rev150602.RouterInterfacesMap.class)
394             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router
395                     .interfaces.map.RouterInterfaces.class,
396                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router
397                     .interfaces.map.RouterInterfacesKey(new Uuid(routerName)))
398             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces
399                     .map.router.interfaces.Interfaces.class,
400                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces
401                     .map.router.interfaces.InterfacesKey(interfaceName)).build();
402     }
403
404     private static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
405         .rev150602.router.interfaces.map.RouterInterfaces> getRoutersInterfacesIdentifier(String routerName) {
406         return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
407             .rev150602.RouterInterfacesMap.class)
408             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router
409                     .interfaces.map.RouterInterfaces.class,
410                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router
411                     .interfaces.map.RouterInterfacesKey(new Uuid(routerName))).build();
412     }
413
414     static InstanceIdentifier<RouterPorts> getRouterPortsId(String routerId) {
415         return InstanceIdentifier.builder(FloatingIpInfo.class)
416             .child(RouterPorts.class, new RouterPortsKey(routerId)).build();
417     }
418
419     static InstanceIdentifier<Routermapping> getRouterVpnMappingId(String routerId) {
420         return InstanceIdentifier.builder(RouterToVpnMapping.class)
421             .child(Routermapping.class, new RoutermappingKey(routerId)).build();
422     }
423
424     static InstanceIdentifier<Ports> getPortsIdentifier(String routerId, String portName) {
425         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId))
426             .child(Ports.class, new PortsKey(portName)).build();
427     }
428
429     static InstanceIdentifier<InternalToExternalPortMap> getIntExtPortMapIdentifier(String routerId, String portName,
430                                                                                     String internalIp) {
431         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId))
432             .child(Ports.class, new PortsKey(portName))
433             .child(InternalToExternalPortMap.class, new InternalToExternalPortMapKey(internalIp)).build();
434     }
435
436     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
437         .instance.to.vpn.id.VpnInstance> getVpnInstanceToVpnIdIdentifier(String vpnName) {
438         return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
439             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
440                     .instance.to.vpn.id.VpnInstance.class,
441                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
442                     .instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
443     }
444
445     @Nullable
446     static String getVpnInstanceFromVpnIdentifier(DataBroker broker, long vpnId) {
447         InstanceIdentifier<VpnIds> id = InstanceIdentifier.builder(VpnIdToVpnInstance.class)
448             .child(VpnIds.class, new VpnIdsKey(vpnId)).build();
449         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
450                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(VpnIds::getVpnInstanceName).orElse(null);
451     }
452
453     /*
454        getFlowRef() returns a string identfier for the SNAT flows using the router ID as the reference.
455     */
456     public static String getFlowRef(BigInteger dpnId, short tableId, long routerID, String ip) {
457         return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId)
458             .append(NatConstants.FLOWID_SEPARATOR).append(tableId).append(NatConstants.FLOWID_SEPARATOR)
459             .append(routerID).append(NatConstants.FLOWID_SEPARATOR).append(ip).toString();
460     }
461
462     public static String getFlowRef(BigInteger dpnId, short tableId, InetAddress destPrefix, long vpnId) {
463         return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId)
464             .append(NatConstants.FLOWID_SEPARATOR).append(tableId).append(NatConstants.FLOWID_SEPARATOR)
465             .append(destPrefix.getHostAddress()).append(NatConstants.FLOWID_SEPARATOR).append(vpnId).toString();
466     }
467
468     public static String getNaptFlowRef(BigInteger dpnId, short tableId, String routerID, String ip,
469         int port, String protocol) {
470         return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId)
471             .append(NatConstants.FLOWID_SEPARATOR).append(tableId).append(NatConstants.FLOWID_SEPARATOR)
472             .append(routerID).append(NatConstants.FLOWID_SEPARATOR).append(ip).append(NatConstants.FLOWID_SEPARATOR)
473             .append(port).append(NatConstants.FLOWID_SEPARATOR).append(protocol).toString();
474     }
475
476     @Nullable
477     static Uuid getNetworkIdFromRouterId(DataBroker broker, long routerId) {
478         String routerName = getRouterName(broker, routerId);
479         if (routerName == null) {
480             LOG.error("getNetworkIdFromRouterId - empty routerName received");
481             return null;
482         }
483         return getNetworkIdFromRouterName(broker, routerName);
484     }
485
486     @Nullable
487     static Uuid getNetworkIdFromRouterName(DataBroker broker, String routerName) {
488         if (routerName == null) {
489             LOG.error("getNetworkIdFromRouterName - empty routerName received");
490             return null;
491         }
492         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerName);
493         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
494                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(Routers::getNetworkId).orElse(null);
495     }
496
497     static InstanceIdentifier<Routers> buildRouterIdentifier(String routerId) {
498         InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class)
499             .child(Routers.class, new RoutersKey(routerId)).build();
500         return routerInstanceIndentifier;
501     }
502
503     private static InstanceIdentifier<RouterIds> buildRouterIdentifier(Long routerId) {
504         InstanceIdentifier<RouterIds> routerIds = InstanceIdentifier.builder(RouterIdName.class)
505             .child(RouterIds.class, new RouterIdsKey(routerId)).build();
506         return routerIds;
507     }
508
509     /**
510      * Return if SNAT is enabled for the given router.
511      *
512      * @param broker   The DataBroker
513      * @param routerId The router
514      * @return boolean true if enabled, otherwise false
515      */
516     static boolean isSnatEnabledForRouterId(DataBroker broker, String routerId) {
517         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerId);
518         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
519                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(Routers::isEnableSnat).orElse(false);
520     }
521
522     @Nullable
523     public static Uuid getVpnIdfromNetworkId(DataBroker broker, Uuid networkId) {
524         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
525         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
526                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(Networks::getVpnid).orElse(null);
527     }
528
529     @Nullable
530     public static Uuid getVpnIdfromNetworkId(TypedReadTransaction<Configuration> tx, Uuid networkId) {
531         try {
532             return tx.read(buildNetworkIdentifier(networkId)).get().toJavaUtil().map(Networks::getVpnid).orElse(null);
533         } catch (InterruptedException | ExecutionException e) {
534             LOG.error("Error reading network VPN id for {}", networkId, e);
535             return null;
536         }
537     }
538
539     @Nullable
540     public static ProviderTypes getProviderTypefromNetworkId(DataBroker broker, Uuid networkId) {
541         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
542         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
543                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(Networks::getProviderNetworkType).orElse(null);
544     }
545
546     @Nullable
547     public static ProviderTypes getProviderTypefromNetworkId(TypedReadTransaction<Configuration> tx, Uuid networkId) {
548         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
549         try {
550             return tx.read(id).get().toJavaUtil().map(Networks::getProviderNetworkType).orElse(null);
551         } catch (InterruptedException | ExecutionException e) {
552             LOG.error("Error retrieving provider type for {}", networkId, e);
553             return null;
554         }
555     }
556
557     @Nullable
558     static String getAssociatedExternalNetwork(DataBroker dataBroker, String routerId) {
559         InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
560         Optional<Routers> routerData =
561                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
562                         LogicalDatastoreType.CONFIGURATION, id);
563         if (routerData.isPresent()) {
564             Uuid networkId = routerData.get().getNetworkId();
565             if (networkId != null) {
566                 return networkId.getValue();
567             }
568         }
569         LOG.info("getAssociatedExternalNetwork : External Network missing for routerid : {}", routerId);
570         return null;
571     }
572
573     private static InstanceIdentifier<Networks> buildNetworkIdentifier(Uuid networkId) {
574         return InstanceIdentifier.builder(ExternalNetworks.class)
575             .child(Networks.class, new NetworksKey(networkId)).build();
576     }
577
578     @Nullable
579     public static BigInteger getPrimaryNaptfromRouterId(DataBroker broker, Long routerId) {
580         // convert routerId to Name
581         String routerName = getRouterName(broker, routerId);
582         if (routerName == null) {
583             LOG.error("getPrimaryNaptfromRouterId - empty routerName received");
584             return null;
585         }
586         return getPrimaryNaptfromRouterName(broker, routerName);
587     }
588
589     @Nullable
590     public static BigInteger getPrimaryNaptfromRouterName(DataBroker broker, String routerName) {
591         if (routerName == null) {
592             LOG.error("getPrimaryNaptfromRouterName - empty routerName received");
593             return null;
594         }
595         InstanceIdentifier<RouterToNaptSwitch> id = buildNaptSwitchIdentifier(routerName);
596         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
597                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(RouterToNaptSwitch::getPrimarySwitchId).orElse(
598                 null);
599     }
600
601     public static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchIdentifier(String routerId) {
602         return InstanceIdentifier.builder(NaptSwitches.class).child(RouterToNaptSwitch.class,
603             new RouterToNaptSwitchKey(routerId)).build();
604     }
605
606     public static Optional<NaptSwitches> getAllPrimaryNaptSwitches(DataBroker broker) {
607         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
608                 LogicalDatastoreType.CONFIGURATION, getNaptSwitchesIdentifier());
609     }
610
611     @Nullable
612     public static String getRouterName(DataBroker broker, Long routerId) {
613         return getVpnInstanceFromVpnIdentifier(broker, routerId);
614     }
615
616     static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String vrfId) {
617         return InstanceIdentifier.builder(VpnInstanceOpData.class)
618             .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vrfId)).build();
619     }
620
621     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, BigInteger cookie, String flowId) {
622         return new FlowEntityBuilder()
623                 .setDpnId(dpnId)
624                 .setTableId(tableId)
625                 .setCookie(cookie)
626                 .setFlowId(flowId)
627                 .build();
628     }
629
630     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId) {
631         return new FlowEntityBuilder()
632                 .setDpnId(dpnId)
633                 .setTableId(tableId)
634                 .setFlowId(flowId)
635                 .build();
636     }
637
638     @Nullable
639     public static String getEndpointIpAddressForDPN(DataBroker broker, BigInteger dpnId) {
640         String nextHopIp = null;
641         InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
642             InstanceIdentifier.builder(DpnEndpoints.class)
643                 .child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpnId)).build();
644         Optional<DPNTEPsInfo> tunnelInfo =
645                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
646                         LogicalDatastoreType.CONFIGURATION, tunnelInfoId);
647         if (tunnelInfo.isPresent()) {
648             List<TunnelEndPoints> nexthopIpList = tunnelInfo.get().getTunnelEndPoints();
649             if (nexthopIpList != null && !nexthopIpList.isEmpty()) {
650                 nextHopIp = nexthopIpList.get(0).getIpAddress().stringValue();
651             }
652         }
653         return nextHopIp;
654     }
655
656     @Nullable
657     public static String getVpnRd(DataBroker broker, String vpnName) {
658         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
659             .instance.to.vpn.id.VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
660         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
661                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
662                 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
663                         .VpnInstance::getVrfId).orElse(null);
664     }
665
666     @Nullable
667     public static String getVpnRd(TypedReadTransaction<Configuration> tx, String vpnName) {
668         try {
669             return tx.read(getVpnInstanceToVpnIdIdentifier(vpnName)).get().toJavaUtil().map(
670                 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
671                     .VpnInstance::getVrfId).orElse(null);
672         } catch (InterruptedException | ExecutionException e) {
673             LOG.error("Error reading the VPN VRF id for {}", vpnName, e);
674             return null;
675         }
676     }
677
678     @Nullable
679     public static IpPortExternal getExternalIpPortMap(DataBroker broker, Long routerId, String internalIpAddress,
680                                                       String internalPort, NAPTEntryEvent.Protocol protocol) {
681         ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
682         InstanceIdentifier<IpPortMap> ipPortMapId =
683             buildIpToPortMapIdentifier(routerId, internalIpAddress, internalPort, protocolType);
684         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
685                 LogicalDatastoreType.CONFIGURATION, ipPortMapId).toJavaUtil().map(IpPortMap::getIpPortExternal).orElse(
686                 null);
687     }
688
689     private static InstanceIdentifier<IpPortMap> buildIpToPortMapIdentifier(Long routerId, String internalIpAddress,
690                                                                             String internalPort,
691                                                                             ProtocolTypes protocolType) {
692         return InstanceIdentifier.builder(IntextIpPortMap.class)
693             .child(IpPortMapping.class, new IpPortMappingKey(routerId))
694             .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
695             .child(IpPortMap.class, new IpPortMapKey(internalIpAddress + ":" + internalPort)).build();
696     }
697
698     static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
699         return InstanceIdentifier.builder(VpnInterfaces.class)
700             .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build();
701     }
702
703     @Nullable
704     public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
705         /*
706          * NodeConnectorId is of form 'openflow:dpnid:portnum'
707          */
708         String[] split = portId.getValue().split(OF_URI_SEPARATOR);
709         if (split.length != 3) {
710             LOG.error("getDpnFromNodeConnectorId : invalid portid : {}", portId.getValue());
711             return null;
712         }
713         return split[1];
714     }
715
716     public static BigInteger getDpIdFromInterface(
717         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
718             .state.Interface ifState) {
719         String lowerLayerIf = ifState.getLowerLayerIf().get(0);
720         NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
721         return new BigInteger(getDpnFromNodeConnectorId(nodeConnectorId));
722     }
723
724
725     @Nullable
726     public static String getRouterIdfromVpnInstance(DataBroker broker, String vpnName, String ipAddress) {
727         // returns only router, attached to IPv4 networks
728         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
729             .child(VpnMap.class, new VpnMapKey(new Uuid(vpnName))).build();
730         Optional<VpnMap> optionalVpnMap =
731                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
732                         LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
733         if (!optionalVpnMap.isPresent()) {
734             LOG.error("getRouterIdfromVpnInstance : Router not found for vpn : {}", vpnName);
735             return null;
736         }
737         List<Uuid> routerIdsList = NeutronUtils.getVpnMapRouterIdsListUuid(optionalVpnMap.get().getRouterIds());
738         if (routerIdsList != null && !routerIdsList.isEmpty()) {
739             for (Uuid routerUuid : routerIdsList) {
740                 InstanceIdentifier<Routers> id = buildRouterIdentifier(routerUuid.getValue());
741                 Optional<Routers> routerData =
742                         SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
743                                 LogicalDatastoreType.CONFIGURATION, id);
744                 if (routerData.isPresent()) {
745                     List<Uuid> subnetIdsList = routerData.get().getSubnetIds();
746                     for (Uuid subnetUuid : subnetIdsList) {
747                         String subnetIp = getSubnetIp(broker, subnetUuid);
748                         SubnetUtils subnet = new SubnetUtils(subnetIp);
749                         if (subnet.getInfo().isInRange(ipAddress)) {
750                             return routerUuid.getValue();
751                         }
752                     }
753                 }
754             }
755         }
756         LOG.info("getRouterIdfromVpnInstance : Router not found for vpn : {}", vpnName);
757         return null;
758     }
759
760     @Nullable
761     static Uuid getVpnForRouter(DataBroker broker, String routerId) {
762         Preconditions.checkNotNull(routerId, "dissociateRouter: routerId not found!");
763         InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
764         Optional<VpnMaps> optionalVpnMaps =
765                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
766                         LogicalDatastoreType.CONFIGURATION, vpnMapsIdentifier);
767         if (optionalVpnMaps.isPresent() && optionalVpnMaps.get().getVpnMap() != null) {
768             for (VpnMap vpnMap : optionalVpnMaps.get().nonnullVpnMap()) {
769                 if (routerId.equals(vpnMap.getVpnId().getValue())) {
770                     continue;
771                 }
772                 List<Uuid> routerIdsList = NeutronUtils.getVpnMapRouterIdsListUuid(vpnMap.getRouterIds());
773                 if (routerIdsList.isEmpty()) {
774                     continue;
775                 }
776                 // Skip router vpnId fetching from internet BGP-VPN
777                 if (vpnMap.getNetworkIds() != null && !vpnMap.getNetworkIds().isEmpty()) {
778                     // We only need to check the first network; if it’s not an external network there’s no
779                     // need to check the rest of the VPN’s network list
780                     if (isExternalNetwork(broker, vpnMap.getNetworkIds().iterator().next())) {
781                         continue;
782                     }
783                 }
784                 if (routerIdsList.contains(new Uuid(routerId))) {
785                     return vpnMap.getVpnId();
786                 }
787             }
788         }
789         LOG.debug("getVpnForRouter : VPN not found for routerID:{}", routerId);
790         return null;
791     }
792
793     static long getAssociatedVpn(DataBroker broker, String routerName) {
794         InstanceIdentifier<Routermapping> routerMappingId = NatUtil.getRouterVpnMappingId(routerName);
795         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
796                 LogicalDatastoreType.OPERATIONAL, routerMappingId).toJavaUtil().map(Routermapping::getVpnId).orElse(
797                 Long.valueOf(NatConstants.INVALID_ID));
798     }
799
800     @Nullable
801     public static String getAssociatedVPN(DataBroker dataBroker, Uuid networkId) {
802         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
803         if (vpnUuid == null) {
804             LOG.error("getAssociatedVPN : No VPN instance associated with ext network {}", networkId);
805             return null;
806         }
807         return vpnUuid.getValue();
808     }
809
810     @Nullable
811     public static String getAssociatedVPN(TypedReadTransaction<Configuration> tx, Uuid networkId) {
812         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(tx, networkId);
813         if (vpnUuid == null) {
814             LOG.error("getAssociatedVPN : No VPN instance associated with ext network {}", networkId);
815             return null;
816         }
817         return vpnUuid.getValue();
818     }
819
820     // TODO Clean up the exception handling
821     @SuppressWarnings("checkstyle:IllegalCatch")
822     public static void addPrefixToBGP(DataBroker broker,
823                                       IBgpManager bgpManager,
824                                       IFibManager fibManager,
825                                       String vpnName,
826                                       String rd,
827                                       String prefix,
828                                       String nextHopIp,
829                                       @Nullable String parentVpnRd,
830                                       @Nullable String macAddress,
831                                       long label,
832                                       long l3vni,
833                                       RouteOrigin origin,
834                                       BigInteger dpId) {
835         try {
836             LOG.info("addPrefixToBGP : Adding Fib entry rd {} prefix {} nextHop {} label {}", rd,
837                     prefix, nextHopIp, label);
838             if (nextHopIp == null) {
839                 LOG.error("addPrefixToBGP : prefix {} rd {} failed since nextHopIp cannot be null.",
840                         prefix, rd);
841                 return;
842             }
843
844             addPrefixToInterface(broker, getVpnId(broker, vpnName), null /*interfaceName*/,prefix, parentVpnRd,
845                 dpId, Prefixes.PrefixCue.Nat);
846             fibManager.addOrUpdateFibEntry(rd, macAddress, prefix,
847                     Collections.singletonList(nextHopIp), VrfEntry.EncapType.Mplsgre, (int)label, l3vni /*l3vni*/,
848                     null /*gatewayMacAddress*/, parentVpnRd, origin, null /*writeTxn*/);
849             if (rd != null && !rd.equalsIgnoreCase(vpnName)) {
850             /* Publish to Bgp only if its an INTERNET VPN */
851                 bgpManager.advertisePrefix(rd, null /*macAddress*/, prefix, Collections.singletonList(nextHopIp),
852                         VrfEntry.EncapType.Mplsgre, (int) label, 0 /*l3vni*/, 0 /*l2vni*/,
853                         null /*gatewayMac*/);
854             }
855             LOG.info("addPrefixToBGP : Added Fib entry rd {} prefix {} nextHop {} label {}", rd,
856                     prefix, nextHopIp, label);
857         } catch (Exception e) {
858             LOG.error("addPrefixToBGP : Add prefix rd {} prefix {} nextHop {} label {} failed", rd,
859                     prefix, nextHopIp, label, e);
860         }
861     }
862
863     static void addPrefixToInterface(DataBroker broker, long vpnId, @Nullable String interfaceName, String ipPrefix,
864                                      String networkId, BigInteger dpId, Prefixes.PrefixCue prefixCue) {
865         InstanceIdentifier<Prefixes> prefixId = InstanceIdentifier.builder(PrefixToInterface.class)
866                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
867                         .VpnIds.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix
868                         .to._interface.VpnIdsKey(vpnId))
869                 .child(Prefixes.class, new PrefixesKey(ipPrefix)).build();
870         PrefixesBuilder prefixBuilder = new PrefixesBuilder().setDpnId(dpId).setIpAddress(ipPrefix);
871         prefixBuilder.setVpnInterfaceName(interfaceName).setPrefixCue(prefixCue);
872         prefixBuilder.setNetworkId(new Uuid(networkId));
873         try {
874             SingleTransactionDataBroker.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, prefixId,
875                     prefixBuilder.build());
876         } catch (TransactionCommitFailedException e) {
877             LOG.error("addPrefixToInterface : Failed to write prefxi-to-interface for {} vpn-id {} DPN {}",
878                     ipPrefix, vpnId, dpId, e);
879         }
880     }
881
882     public static void deletePrefixToInterface(DataBroker broker, long vpnId, String ipPrefix) {
883         try {
884             SingleTransactionDataBroker.syncDelete(broker, LogicalDatastoreType.OPERATIONAL,
885                     InstanceIdentifier.builder(PrefixToInterface.class)
886                     .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
887                             .VpnIds.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
888                             .prefix.to._interface.VpnIdsKey(vpnId)).child(Prefixes.class, new PrefixesKey(ipPrefix))
889                     .build());
890         } catch (TransactionCommitFailedException e) {
891             LOG.error("addPrefixToInterface : Failed to write prefxi-to-interface for vpn-id {}",
892                     vpnId, e);
893         }
894     }
895
896     static InstanceIdentifier<Ports> buildPortToIpMapIdentifier(String routerId, String portName) {
897         InstanceIdentifier<Ports> ipPortMapId = InstanceIdentifier.builder(FloatingIpInfo.class)
898             .child(RouterPorts.class, new RouterPortsKey(routerId)).child(Ports.class, new PortsKey(portName)).build();
899         return ipPortMapId;
900     }
901
902     static InstanceIdentifier<RouterPorts> buildRouterPortsIdentifier(String routerId) {
903         InstanceIdentifier<RouterPorts> routerInstanceIndentifier = InstanceIdentifier.builder(FloatingIpInfo.class)
904             .child(RouterPorts.class, new RouterPortsKey(routerId)).build();
905         return routerInstanceIndentifier;
906     }
907
908     @NonNull
909     public static List<Integer> getInternalIpPortListInfo(DataBroker dataBroker, Long routerId,
910                                                           String internalIpAddress, ProtocolTypes protocolType) {
911         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
912                 LogicalDatastoreType.CONFIGURATION,
913                 buildSnatIntIpPortIdentifier(routerId, internalIpAddress, protocolType)).toJavaUtil().map(
914                 IntIpProtoType::getPorts).orElse(emptyList());
915     }
916
917     public static InstanceIdentifier<IntIpProtoType> buildSnatIntIpPortIdentifier(Long routerId,
918                                                                                   String internalIpAddress,
919                                                                                   ProtocolTypes protocolType) {
920         InstanceIdentifier<IntIpProtoType> intIpProtocolTypeId =
921             InstanceIdentifier.builder(SnatintIpPortMap.class)
922                 .child(IntipPortMap.class, new IntipPortMapKey(routerId))
923                 .child(IpPort.class, new IpPortKey(internalIpAddress))
924                 .child(IntIpProtoType.class, new IntIpProtoTypeKey(protocolType)).build();
925         return intIpProtocolTypeId;
926     }
927
928     public static InstanceIdentifier<IpPort> buildSnatIntIpPortIdentifier(Long routerId,
929             String internalIpAddress) {
930         InstanceIdentifier<IpPort> intIpProtocolTypeId =
931             InstanceIdentifier.builder(SnatintIpPortMap.class)
932                 .child(IntipPortMap.class, new IntipPortMapKey(routerId))
933                 .child(IpPort.class, new IpPortKey(internalIpAddress)).build();
934         return intIpProtocolTypeId;
935     }
936
937     @Nullable
938     public static IpPort getInternalIpPortInfo(DataBroker dataBroker, Long routerId,
939                                                           String internalIpAddress) {
940         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
941                 LogicalDatastoreType.CONFIGURATION,
942                 buildSnatIntIpPortIdentifier(routerId, internalIpAddress)).orNull();
943     }
944
945     public static ProtocolTypes getProtocolType(NAPTEntryEvent.Protocol protocol) {
946         ProtocolTypes protocolType = ProtocolTypes.TCP.toString().equals(protocol.toString())
947             ? ProtocolTypes.TCP : ProtocolTypes.UDP;
948         return protocolType;
949     }
950
951     public static InstanceIdentifier<NaptSwitches> getNaptSwitchesIdentifier() {
952         return InstanceIdentifier.create(NaptSwitches.class);
953     }
954
955     public static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchRouterIdentifier(String routerId) {
956         return InstanceIdentifier.create(NaptSwitches.class)
957             .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerId));
958     }
959
960     public static String getGroupIdKey(String routerName) {
961         return "snatmiss." + routerName;
962     }
963
964     public static int getUniqueId(IdManagerService idManager, String poolName, String idKey) {
965
966         AllocateIdInput getIdInput = (new AllocateIdInputBuilder()).setPoolName(poolName).setIdKey(idKey).build();
967         try {
968             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
969             RpcResult<AllocateIdOutput> rpcResult = (RpcResult)result.get();
970             return rpcResult.isSuccessful() ? rpcResult.getResult().getIdValue().intValue() : NatConstants.INVALID_ID;
971         } catch (InterruptedException | ExecutionException e) {
972             LOG.error("releaseId: Exception when releasing Id for key {} from pool {}", idKey, poolName, e);
973         }
974         return NatConstants.INVALID_ID;
975     }
976
977     public static Integer releaseId(IdManagerService idManager, String poolName, String idKey) {
978         ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
979         try {
980             Future<RpcResult<ReleaseIdOutput>> result = idManager.releaseId(idInput);
981             if (result == null || result.get() == null || !result.get().isSuccessful()) {
982                 LOG.error("releaseId: RPC Call to release Id from pool {} with key {} returned with Errors {}",
983                     poolName, idKey,
984                     (result != null && result.get() != null) ? result.get().getErrors() : "RpcResult is null");
985             } else {
986                 return 1;
987             }
988         } catch (InterruptedException | ExecutionException e) {
989             LOG.error("releaseId: Exception when releasing Id for key {} from pool {}", idKey, poolName, e);
990         }
991         return NatConstants.INVALID_ID;
992     }
993
994     // TODO Clean up the exception handling
995     @SuppressWarnings("checkstyle:IllegalCatch")
996     public static void removePrefixFromBGP(IBgpManager bgpManager, IFibManager fibManager,
997                                            String rd, String prefix, String vpnName) {
998         try {
999             LOG.debug("removePrefixFromBGP: Removing Fib entry rd {} prefix {}", rd, prefix);
1000             fibManager.removeFibEntry(rd, prefix, null);
1001             if (rd != null && !rd.equalsIgnoreCase(vpnName)) {
1002                 bgpManager.withdrawPrefix(rd, prefix);
1003             }
1004             LOG.info("removePrefixFromBGP: Removed Fib entry rd {} prefix {}", rd, prefix);
1005         } catch (Exception e) {
1006             LOG.error("removePrefixFromBGP : Delete prefix for rd {} prefix {} vpnName {} failed",
1007                     rd, prefix, vpnName, e);
1008         }
1009     }
1010
1011     @Nullable
1012     public static IpPortMapping getIportMapping(DataBroker broker, long routerId) {
1013         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1014                 LogicalDatastoreType.CONFIGURATION, getIportMappingIdentifier(routerId)).orNull();
1015     }
1016
1017     public static InstanceIdentifier<IpPortMapping> getIportMappingIdentifier(long routerId) {
1018         return InstanceIdentifier.builder(IntextIpPortMap.class)
1019             .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
1020     }
1021
1022     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
1023         .natservice.rev160111.intext.ip.map.IpMapping> getIpMappingBuilder(Long routerId) {
1024         return InstanceIdentifier.builder(IntextIpMap.class)
1025             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map
1026                 .IpMapping.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111
1027                 .intext.ip.map.IpMappingKey(routerId))
1028             .build();
1029     }
1030
1031     @NonNull
1032     public static Collection<String> getExternalIpsForRouter(DataBroker dataBroker, Long routerId) {
1033         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext
1034             .ip.map.IpMapping> ipMappingOptional =
1035                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1036                         LogicalDatastoreType.OPERATIONAL, getIpMappingBuilder(routerId));
1037         // Ensure there are no duplicates
1038         Collection<String> externalIps = new HashSet<>();
1039         if (ipMappingOptional.isPresent()) {
1040             for (IpMap ipMap : ipMappingOptional.get().nonnullIpMap()) {
1041                 externalIps.add(ipMap.getExternalIp());
1042             }
1043         }
1044         return externalIps;
1045     }
1046
1047     @NonNull
1048     public static List<String> getExternalIpsForRouter(DataBroker dataBroker, String routerName) {
1049         Routers routerData = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
1050         if (routerData != null) {
1051             return NatUtil.getIpsListFromExternalIps(routerData.getExternalIps());
1052         }
1053
1054         return emptyList();
1055     }
1056
1057     @NonNull
1058     public static Map<String, Long> getExternalIpsLabelForRouter(DataBroker dataBroker, Long routerId) {
1059         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext
1060             .ip.map.IpMapping> ipMappingOptional =
1061                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1062                         LogicalDatastoreType.OPERATIONAL, getIpMappingBuilder(routerId));
1063         Map<String, Long> externalIpsLabel = new HashMap<>();
1064         if (ipMappingOptional.isPresent()) {
1065             for (IpMap ipMap : ipMappingOptional.get().nonnullIpMap()) {
1066                 externalIpsLabel.put(ipMap.getExternalIp(), ipMap.getLabel());
1067             }
1068         }
1069         return externalIpsLabel;
1070     }
1071
1072     @Nullable
1073     public static String getLeastLoadedExternalIp(DataBroker dataBroker, long segmentId) {
1074         String leastLoadedExternalIp = null;
1075         InstanceIdentifier<ExternalCounters> id =
1076             InstanceIdentifier.builder(ExternalIpsCounter.class)
1077                 .child(ExternalCounters.class, new ExternalCountersKey(segmentId)).build();
1078         Optional<ExternalCounters> externalCountersData =
1079             MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
1080         if (externalCountersData.isPresent()) {
1081             ExternalCounters externalCounter = externalCountersData.get();
1082             short countOfLstLoadExtIp = 32767;
1083             for (ExternalIpCounter externalIpCounter : externalCounter.nonnullExternalIpCounter()) {
1084                 String curExternalIp = externalIpCounter.getExternalIp();
1085                 short countOfCurExtIp = externalIpCounter.getCounter();
1086                 if (countOfCurExtIp < countOfLstLoadExtIp) {
1087                     countOfLstLoadExtIp = countOfCurExtIp;
1088                     leastLoadedExternalIp = curExternalIp;
1089                 }
1090             }
1091         }
1092         return leastLoadedExternalIp;
1093     }
1094
1095     @SuppressFBWarnings("PZLA_PREFER_ZERO_LENGTH_ARRAYS")
1096     @Nullable
1097     public static String[] getSubnetIpAndPrefix(DataBroker dataBroker, Uuid subnetId) {
1098         String subnetIP = getSubnetIp(dataBroker, subnetId);
1099         if (subnetIP != null) {
1100             return getSubnetIpAndPrefix(subnetIP);
1101         }
1102         LOG.error("getSubnetIpAndPrefix : SubnetIP and Prefix missing for subnet : {}", subnetId);
1103         return null;
1104     }
1105
1106     @NonNull
1107     public static String[] getSubnetIpAndPrefix(String subnetString) {
1108         String[] subnetSplit = subnetString.split("/");
1109         String subnetIp = subnetSplit[0];
1110         String subnetPrefix = "0";
1111         if (subnetSplit.length == 2) {
1112             subnetPrefix = subnetSplit[1];
1113         }
1114         return new String[] {subnetIp, subnetPrefix};
1115     }
1116
1117     @Nullable
1118     public static String getSubnetIp(DataBroker dataBroker, Uuid subnetId) {
1119         InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
1120             .builder(Subnetmaps.class)
1121             .child(Subnetmap.class, new SubnetmapKey(subnetId))
1122             .build();
1123         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1124                 LogicalDatastoreType.CONFIGURATION, subnetmapId).toJavaUtil().map(Subnetmap::getSubnetIp).orElse(null);
1125     }
1126
1127     public static String[] getExternalIpAndPrefix(String leastLoadedExtIpAddr) {
1128         String[] leastLoadedExtIpAddrSplit = leastLoadedExtIpAddr.split("/");
1129         String leastLoadedExtIp = leastLoadedExtIpAddrSplit[0];
1130         String leastLoadedExtIpPrefix = String.valueOf(NatConstants.DEFAULT_PREFIX);
1131         if (leastLoadedExtIpAddrSplit.length == 2) {
1132             leastLoadedExtIpPrefix = leastLoadedExtIpAddrSplit[1];
1133         }
1134         return new String[] {leastLoadedExtIp, leastLoadedExtIpPrefix};
1135     }
1136
1137     @NonNull
1138     public static List<BigInteger> getDpnsForRouter(DataBroker dataBroker, String routerUuid) {
1139         InstanceIdentifier id = InstanceIdentifier.builder(NeutronRouterDpns.class)
1140             .child(RouterDpnList.class, new RouterDpnListKey(routerUuid)).build();
1141         Optional<RouterDpnList> routerDpnListData =
1142                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1143                         LogicalDatastoreType.OPERATIONAL, id);
1144         List<BigInteger> dpns = new ArrayList<>();
1145         if (routerDpnListData.isPresent()) {
1146             for (DpnVpninterfacesList dpnVpnInterface : routerDpnListData.get().nonnullDpnVpninterfacesList()) {
1147                 dpns.add(dpnVpnInterface.getDpnId());
1148             }
1149         }
1150         return dpns;
1151     }
1152
1153     public static long getBgpVpnId(DataBroker dataBroker, String routerName) {
1154         long bgpVpnId = NatConstants.INVALID_ID;
1155         Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
1156         if (bgpVpnUuid != null) {
1157             bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
1158         }
1159         return bgpVpnId;
1160     }
1161
1162     static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces
1163             .@Nullable RouterInterface getConfiguredRouterInterface(DataBroker broker, String interfaceName) {
1164         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1165                 LogicalDatastoreType.CONFIGURATION, NatUtil.getRouterInterfaceId(interfaceName)).orNull();
1166     }
1167
1168     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
1169         .router.interfaces.RouterInterface> getRouterInterfaceId(String interfaceName) {
1170         return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight
1171             .netvirt.l3vpn.rev130911.RouterInterfaces.class)
1172             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces
1173                     .RouterInterface.class,
1174                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces
1175                     .RouterInterfaceKey(interfaceName)).build();
1176     }
1177
1178     public static void addToNeutronRouterDpnsMap(String routerName, String interfaceName, BigInteger dpId,
1179         TypedReadWriteTransaction<Operational> operTx) throws ExecutionException, InterruptedException {
1180
1181         if (dpId.equals(BigInteger.ZERO)) {
1182             LOG.warn("addToNeutronRouterDpnsMap : Could not retrieve dp id for interface {} "
1183                     + "to handle router {} association model", interfaceName, routerName);
1184             return;
1185         }
1186
1187         LOG.debug("addToNeutronRouterDpnsMap : Adding the Router {} and DPN {} for the Interface {} in the "
1188                 + "ODL-L3VPN : NeutronRouterDpn map", routerName, dpId, interfaceName);
1189         InstanceIdentifier<DpnVpninterfacesList> dpnVpnInterfacesListIdentifier = getRouterDpnId(routerName, dpId);
1190
1191         Optional<DpnVpninterfacesList> optionalDpnVpninterfacesList = operTx.read(dpnVpnInterfacesListIdentifier).get();
1192         org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns
1193             .router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces routerInterface =
1194             new RouterInterfacesBuilder().withKey(new RouterInterfacesKey(interfaceName))
1195             .setInterface(interfaceName).build();
1196         if (optionalDpnVpninterfacesList.isPresent()) {
1197             LOG.debug("addToNeutronRouterDpnsMap : RouterDpnList already present for the Router {} and DPN {} for the "
1198                     + "Interface {} in the ODL-L3VPN : NeutronRouterDpn map", routerName, dpId, interfaceName);
1199             operTx.merge(dpnVpnInterfacesListIdentifier
1200                     .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1201                             .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
1202                             new RouterInterfacesKey(interfaceName)), routerInterface, CREATE_MISSING_PARENTS);
1203         } else {
1204             LOG.debug("addToNeutronRouterDpnsMap : Building new RouterDpnList for the Router {} and DPN {} for the "
1205                     + "Interface {} in the ODL-L3VPN : NeutronRouterDpn map", routerName, dpId, interfaceName);
1206             RouterDpnListBuilder routerDpnListBuilder = new RouterDpnListBuilder();
1207             routerDpnListBuilder.setRouterId(routerName);
1208             DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1209             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1210                 .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces> routerInterfaces = new ArrayList<>();
1211             routerInterfaces.add(routerInterface);
1212             dpnVpnList.setRouterInterfaces(routerInterfaces);
1213             routerDpnListBuilder.setDpnVpninterfacesList(Collections.singletonList(dpnVpnList.build()));
1214             operTx.merge(getRouterId(routerName), routerDpnListBuilder.build(), CREATE_MISSING_PARENTS);
1215         }
1216     }
1217
1218     public static void addToDpnRoutersMap(String routerName, String interfaceName, BigInteger dpId,
1219         TypedReadWriteTransaction<Operational> operTx) throws ExecutionException, InterruptedException {
1220         if (dpId.equals(BigInteger.ZERO)) {
1221             LOG.error("addToDpnRoutersMap : Could not retrieve dp id for interface {} to handle router {} "
1222                     + "association model", interfaceName, routerName);
1223             return;
1224         }
1225
1226         LOG.debug("addToDpnRoutersMap : Adding the DPN {} and router {} for the Interface {} in the ODL-L3VPN : "
1227                 + "DPNRouters map", dpId, routerName, interfaceName);
1228         InstanceIdentifier<DpnRoutersList> dpnRoutersListIdentifier = getDpnRoutersId(dpId);
1229
1230         Optional<DpnRoutersList> optionalDpnRoutersList = operTx.read(dpnRoutersListIdentifier).get();
1231
1232         if (optionalDpnRoutersList.isPresent()) {
1233             RoutersList routersList = new RoutersListBuilder().withKey(new RoutersListKey(routerName))
1234                     .setRouter(routerName).build();
1235             List<RoutersList> routersListFromDs = optionalDpnRoutersList.get().nonnullRoutersList();
1236             if (!routersListFromDs.contains(routersList)) {
1237                 LOG.debug("addToDpnRoutersMap : Router {} not present for the DPN {}"
1238                         + " in the ODL-L3VPN : DPNRouters map", routerName, dpId);
1239                 operTx.merge(dpnRoutersListIdentifier
1240                         .child(RoutersList.class, new RoutersListKey(routerName)), routersList, CREATE_MISSING_PARENTS);
1241             } else {
1242                 LOG.debug("addToDpnRoutersMap : Router {} already mapped to the DPN {} in the ODL-L3VPN : "
1243                         + "DPNRouters map", routerName, dpId);
1244             }
1245         } else {
1246             LOG.debug("addToDpnRoutersMap : Building new DPNRoutersList for the Router {} present in the DPN {} "
1247                     + "ODL-L3VPN : DPNRouters map", routerName, dpId);
1248             DpnRoutersListBuilder dpnRoutersListBuilder = new DpnRoutersListBuilder();
1249             dpnRoutersListBuilder.setDpnId(dpId);
1250             RoutersListBuilder routersListBuilder = new RoutersListBuilder();
1251             routersListBuilder.setRouter(routerName);
1252             dpnRoutersListBuilder.setRoutersList(Collections.singletonList(routersListBuilder.build()));
1253             operTx.merge(getDpnRoutersId(dpId), dpnRoutersListBuilder.build(), CREATE_MISSING_PARENTS);
1254         }
1255     }
1256
1257     public static void removeFromNeutronRouterDpnsMap(String routerName, BigInteger dpId,
1258         TypedReadWriteTransaction<Operational> operTx) throws ExecutionException, InterruptedException {
1259         if (dpId.equals(BigInteger.ZERO)) {
1260             LOG.warn("removeFromNeutronRouterDpnsMap : DPN ID is invalid for the router {} ", routerName);
1261             return;
1262         }
1263
1264         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1265         Optional<DpnVpninterfacesList> optionalRouterDpnList = operTx.read(routerDpnListIdentifier).get();
1266         if (optionalRouterDpnList.isPresent()) {
1267             LOG.debug("removeFromNeutronRouterDpnsMap : Removing the dpn-vpninterfaces-list from the "
1268                     + "odl-l3vpn:neutron-router-dpns model for the router {}", routerName);
1269             operTx.delete(routerDpnListIdentifier);
1270         } else {
1271             LOG.debug("removeFromNeutronRouterDpnsMap : dpn-vpninterfaces-list does not exist in the "
1272                     + "odl-l3vpn:neutron-router-dpns model for the router {}", routerName);
1273         }
1274     }
1275
1276     public static void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
1277          BigInteger dpId, @NonNull TypedReadWriteTransaction<Operational> operTx) {
1278         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1279         Optional<DpnVpninterfacesList> optionalRouterDpnList;
1280         try {
1281             optionalRouterDpnList = operTx.read(routerDpnListIdentifier).get();
1282         } catch (InterruptedException | ExecutionException e) {
1283             LOG.error("Error reading the router DPN list for {}", routerDpnListIdentifier, e);
1284             optionalRouterDpnList = Optional.absent();
1285         }
1286         if (optionalRouterDpnList.isPresent()) {
1287             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns
1288                     .router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces> routerInterfaces =
1289                     optionalRouterDpnList.get().getRouterInterfaces();
1290             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn
1291                     .list.dpn.vpninterfaces.list.RouterInterfaces routerInterface =
1292                     new RouterInterfacesBuilder().withKey(new RouterInterfacesKey(vpnInterfaceName))
1293                             .setInterface(vpnInterfaceName).build();
1294
1295             if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1296                 if (routerInterfaces.isEmpty()) {
1297                     operTx.delete(routerDpnListIdentifier);
1298                 } else {
1299                     operTx.delete(routerDpnListIdentifier.child(
1300                             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1301                                     .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
1302                             new RouterInterfacesKey(vpnInterfaceName)));
1303                 }
1304             }
1305         }
1306     }
1307
1308     public static void removeFromDpnRoutersMap(DataBroker broker, String routerName, String vpnInterfaceName,
1309         BigInteger curDpnId, OdlInterfaceRpcService ifaceMgrRpcService, TypedReadWriteTransaction<Operational> operTx)
1310         throws ExecutionException, InterruptedException {
1311         /*
1312             1) Get the DpnRoutersList for the DPN.
1313             2) Get the RoutersList identifier for the DPN and router.
1314             3) Get the VPN interfaces for the router (routerList) through which it is connected to the DPN.
1315             4) If the removed VPN interface is the only interface through which the router is connected to the DPN,
1316              then remove RouterList.
1317          */
1318
1319         LOG.debug("removeFromDpnRoutersMap() : Removing the DPN {} and router {} for the Interface {}"
1320             + " in the ODL-L3VPN : DPNRouters map", curDpnId, routerName, vpnInterfaceName);
1321
1322         //Get the dpn-routers-list instance for the current DPN.
1323         InstanceIdentifier<DpnRoutersList> dpnRoutersListIdentifier = getDpnRoutersId(curDpnId);
1324         Optional<DpnRoutersList> dpnRoutersListData = operTx.read(dpnRoutersListIdentifier).get();
1325
1326         if (dpnRoutersListData == null || !dpnRoutersListData.isPresent()) {
1327             LOG.error("removeFromDpnRoutersMap : dpn-routers-list is not present for DPN {} "
1328                     + "in the ODL-L3VPN:dpn-routers model", curDpnId);
1329             return;
1330         }
1331
1332         //Get the routers-list instance for the router on the current DPN only
1333         InstanceIdentifier<RoutersList> routersListIdentifier = getRoutersList(curDpnId, routerName);
1334         Optional<RoutersList> routersListData = operTx.read(routersListIdentifier).get();
1335
1336         if (routersListData == null || !routersListData.isPresent()) {
1337             LOG.error("removeFromDpnRoutersMap : routers-list is not present for the DPN {} "
1338                     + "in the ODL-L3VPN:dpn-routers model",
1339                 curDpnId);
1340             return;
1341         }
1342
1343         LOG.debug("removeFromDpnRoutersMap : Get the interfaces for the router {} "
1344                 + "from the NeutronVPN - router-interfaces-map", routerName);
1345         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router
1346             .interfaces.map.RouterInterfaces> routerInterfacesId = getRoutersInterfacesIdentifier(routerName);
1347         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map
1348                 .RouterInterfaces> routerInterfacesData =
1349                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1350                         LogicalDatastoreType.CONFIGURATION, routerInterfacesId);
1351
1352         if (routerInterfacesData == null || !routerInterfacesData.isPresent()) {
1353             LOG.debug("removeFromDpnRoutersMap : Unable to get the routers list for the DPN {}. Possibly all subnets "
1354                     + "removed from router {} OR Router {} has been deleted. Hence DPN router model WILL be cleared ",
1355                 curDpnId, routerName, routerName);
1356             operTx.delete(routersListIdentifier);
1357             return;
1358         }
1359
1360         //Get the VM interfaces for the router on the current DPN only.
1361         List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces
1362             .map.router.interfaces.Interfaces> vmInterfaces = routerInterfacesData.get().getInterfaces();
1363         if (vmInterfaces == null) {
1364             LOG.debug("removeFromDpnRoutersMap : VM interfaces are not present for the router {} in the "
1365                 + "NeutronVPN - router-interfaces-map", routerName);
1366             return;
1367         }
1368
1369         // If the removed VPN interface is the only interface through which the router is connected to the DPN,
1370         // then remove RouterList.
1371         for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map
1372                  .router.interfaces.Interfaces vmInterface : vmInterfaces) {
1373             String vmInterfaceName = vmInterface.getInterfaceId();
1374             BigInteger vmDpnId = getDpnForInterface(ifaceMgrRpcService, vmInterfaceName);
1375             if (vmDpnId.equals(BigInteger.ZERO) || !vmDpnId.equals(curDpnId)) {
1376                 LOG.debug("removeFromDpnRoutersMap : DPN ID {} for the removed interface {} is not the same as that of "
1377                         + "the DPN ID {} for the checked interface {}",
1378                     curDpnId, vpnInterfaceName, vmDpnId, vmInterfaceName);
1379                 continue;
1380             }
1381             if (!vmInterfaceName.equalsIgnoreCase(vpnInterfaceName)) {
1382                 LOG.info("removeFromDpnRoutersMap : Router {} is present in the DPN {} through the other interface {} "
1383                     + "Hence DPN router model WOULD NOT be cleared", routerName, curDpnId, vmInterfaceName);
1384                 return;
1385             }
1386         }
1387         LOG.debug("removeFromDpnRoutersMap : Router {} is present in the DPN {} only through the interface {} "
1388             + "Hence DPN router model WILL be cleared. Possibly last VM for the router "
1389             + "deleted in the DPN", routerName, curDpnId, vpnInterfaceName);
1390         operTx.delete(routersListIdentifier);
1391     }
1392
1393     private static InstanceIdentifier<RoutersList> getRoutersList(BigInteger dpnId, String routerName) {
1394         return InstanceIdentifier.builder(DpnRouters.class)
1395             .child(DpnRoutersList.class, new DpnRoutersListKey(dpnId))
1396             .child(RoutersList.class, new RoutersListKey(routerName)).build();
1397     }
1398
1399     public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
1400         BigInteger nodeId = BigInteger.ZERO;
1401         try {
1402             GetDpidFromInterfaceInput
1403                 dpIdInput =
1404                 new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
1405             Future<RpcResult<GetDpidFromInterfaceOutput>>
1406                 dpIdOutput =
1407                 interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
1408             RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
1409             if (dpIdResult.isSuccessful()) {
1410                 nodeId = dpIdResult.getResult().getDpid();
1411             } else {
1412                 LOG.debug("getDpnForInterface : Could not retrieve DPN Id for interface {}", ifName);
1413             }
1414         } catch (NullPointerException | InterruptedException | ExecutionException e) {
1415             LOG.error("getDpnForInterface : Exception when getting dpn for interface {}", ifName, e);
1416         }
1417         return nodeId;
1418     }
1419
1420     @NonNull
1421     public static List<ActionInfo> getEgressActionsForInterface(OdlInterfaceRpcService odlInterfaceRpcService,
1422                                                                 ItmRpcService itmRpcService,
1423                                                                 IInterfaceManager interfaceManager, String ifName,
1424                                                                 Long tunnelKey, boolean internalTunnelInterface) {
1425         return getEgressActionsForInterface(odlInterfaceRpcService, itmRpcService, interfaceManager,
1426                 ifName, tunnelKey, 0, internalTunnelInterface);
1427     }
1428
1429     @NonNull
1430     public static List<ActionInfo> getEgressActionsForInterface(OdlInterfaceRpcService odlInterfaceRpcService,
1431                                                                 ItmRpcService itmRpcService,
1432                                                                 IInterfaceManager interfaceManager,
1433                                                                 String ifName, @Nullable Long tunnelKey, int pos,
1434                                                                 boolean internalTunnelInterface) {
1435         LOG.debug("getEgressActionsForInterface : called for interface {}", ifName);
1436         GetEgressActionsForInterfaceInputBuilder egressActionsIfmBuilder =
1437                 new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName);
1438         GetEgressActionsForTunnelInputBuilder egressActionsItmBuilder =
1439                 new GetEgressActionsForTunnelInputBuilder().setIntfName(ifName);
1440         if (tunnelKey != null) {
1441             egressActionsIfmBuilder.setTunnelKey(tunnelKey);
1442             egressActionsItmBuilder.setTunnelKey(tunnelKey);
1443         } //init builders, ITM/IFM rpc can be called based on type of interface
1444
1445         try {
1446             List<Action> actions = emptyList();
1447             if (interfaceManager.isItmDirectTunnelsEnabled() && internalTunnelInterface) {
1448                 RpcResult<GetEgressActionsForTunnelOutput> rpcResult =
1449                         itmRpcService.getEgressActionsForTunnel(egressActionsItmBuilder.build()).get();
1450                 if (!rpcResult.isSuccessful()) {
1451                     LOG.error("getEgressActionsForTunnels : RPC Call to Get egress actions for Tunnels {} "
1452                             + "returned with Errors {}", ifName, rpcResult.getErrors());
1453                 } else {
1454                     actions = rpcResult.getResult().nonnullAction();
1455                 }
1456             } else {
1457                 RpcResult<GetEgressActionsForInterfaceOutput> rpcResult =
1458                         odlInterfaceRpcService.getEgressActionsForInterface(egressActionsIfmBuilder.build()).get();
1459                 if (!rpcResult.isSuccessful()) {
1460                     LOG.error("getEgressActionsForInterface : RPC Call to Get egress actions for interface {} "
1461                             + "returned with Errors {}", ifName, rpcResult.getErrors());
1462                 } else {
1463                     actions = rpcResult.getResult().nonnullAction();
1464                 }
1465             }
1466             List<ActionInfo> listActionInfo = new ArrayList<>();
1467             for (Action action : actions) {
1468                 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action
1469                     actionClass = action.getAction();
1470                 if (actionClass instanceof OutputActionCase) {
1471                     listActionInfo.add(new ActionOutput(pos++,
1472                         ((OutputActionCase) actionClass).getOutputAction().getOutputNodeConnector()));
1473                 } else if (actionClass instanceof PushVlanActionCase) {
1474                     listActionInfo.add(new ActionPushVlan(pos++));
1475                 } else if (actionClass instanceof SetFieldCase) {
1476                     if (((SetFieldCase) actionClass).getSetField().getVlanMatch() != null) {
1477                         int vlanVid = ((SetFieldCase) actionClass).getSetField().getVlanMatch().getVlanId()
1478                             .getVlanId().getValue();
1479                         listActionInfo.add(new ActionSetFieldVlanVid(pos++, vlanVid));
1480                     }
1481                 } else if (actionClass instanceof NxActionResubmitRpcAddGroupCase) {
1482                     Short tableId = ((NxActionResubmitRpcAddGroupCase) actionClass).getNxResubmit().getTable();
1483                     listActionInfo.add(new ActionNxResubmit(pos++, tableId));
1484                 } else if (actionClass instanceof NxActionRegLoadNodesNodeTableFlowApplyActionsCase) {
1485                     NxRegLoad nxRegLoad =
1486                         ((NxActionRegLoadNodesNodeTableFlowApplyActionsCase) actionClass).getNxRegLoad();
1487                     listActionInfo.add(new ActionRegLoad(pos++, NxmNxReg6.class, nxRegLoad.getDst().getStart(),
1488                         nxRegLoad.getDst().getEnd(), nxRegLoad.getValue().longValue()));
1489                 }
1490             }
1491             return listActionInfo;
1492         } catch (InterruptedException | ExecutionException e) {
1493             LOG.error("Exception when egress actions for interface {}", ifName, e);
1494         }
1495         LOG.error("Error when getting egress actions for interface {}", ifName);
1496         return emptyList();
1497     }
1498
1499     @Nullable
1500     public static Port getNeutronPortForRouterGetewayIp(DataBroker broker, IpAddress targetIP) {
1501         return getNeutronPortForIp(broker, targetIP, NeutronConstants.DEVICE_OWNER_GATEWAY_INF);
1502     }
1503
1504     @NonNull
1505     public static List<Port> getNeutronPorts(DataBroker broker) {
1506         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports>
1507             portsIdentifier = InstanceIdentifier.create(Neutron.class)
1508             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports.class);
1509         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports>
1510                 portsOptional =
1511                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1512                         LogicalDatastoreType.CONFIGURATION, portsIdentifier);
1513
1514         if (!portsOptional.isPresent() || portsOptional.get().getPort() == null) {
1515             LOG.error("getNeutronPorts : No neutron ports found");
1516             return emptyList();
1517         }
1518
1519         return portsOptional.get().getPort();
1520     }
1521
1522     @Nullable
1523     public static Port getNeutronPortForIp(DataBroker broker, IpAddress targetIP, String deviceType) {
1524         List<Port> ports = getNeutronPorts(
1525             broker);
1526
1527         for (Port port : ports) {
1528             if (deviceType.equals(port.getDeviceOwner()) && port.getFixedIps() != null) {
1529                 for (FixedIps ip : port.getFixedIps()) {
1530                     if (Objects.equals(ip.getIpAddress(), targetIP)) {
1531                         return port;
1532                     }
1533                 }
1534             }
1535         }
1536         LOG.error("getNeutronPortForIp : Neutron Port missing for IP:{} DeviceType:{}", targetIP, deviceType);
1537         return null;
1538     }
1539
1540     @Nullable
1541     public static Uuid getSubnetIdForFloatingIp(Port port, IpAddress targetIP) {
1542         if (port == null) {
1543             LOG.error("getSubnetIdForFloatingIp : port is null");
1544             return null;
1545         }
1546         for (FixedIps ip : port.nonnullFixedIps()) {
1547             if (Objects.equals(ip.getIpAddress(), targetIP)) {
1548                 return ip.getSubnetId();
1549             }
1550         }
1551         LOG.error("getSubnetIdForFloatingIp : No Fixed IP configured for targetIP:{}", targetIP);
1552         return null;
1553     }
1554
1555     @Nullable
1556     public static Subnetmap getSubnetMap(DataBroker broker, Uuid subnetId) {
1557         InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier.builder(Subnetmaps.class)
1558             .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
1559         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1560                 LogicalDatastoreType.CONFIGURATION, subnetmapId).orNull();
1561     }
1562
1563     @NonNull
1564     public static List<Uuid> getSubnetIdsFromNetworkId(DataBroker broker, Uuid networkId) {
1565         InstanceIdentifier<NetworkMap> id = InstanceIdentifier.builder(NetworkMaps.class)
1566             .child(NetworkMap.class, new NetworkMapKey(networkId)).build();
1567         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1568                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(NetworkMap::getSubnetIdList).orElse(
1569                 emptyList());
1570     }
1571
1572     @Nullable
1573     public static String getSubnetGwMac(DataBroker broker, Uuid subnetId, String vpnName) {
1574         if (subnetId == null) {
1575             LOG.error("getSubnetGwMac : subnetID is null");
1576             return null;
1577         }
1578
1579         InstanceIdentifier<Subnet> subnetInst = InstanceIdentifier.create(Neutron.class).child(Subnets.class)
1580             .child(Subnet.class, new SubnetKey(subnetId));
1581         Optional<Subnet> subnetOpt =
1582                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1583                         LogicalDatastoreType.CONFIGURATION, subnetInst);
1584         if (!subnetOpt.isPresent()) {
1585             LOG.error("getSubnetGwMac : unable to obtain Subnet for id : {}", subnetId);
1586             return null;
1587         }
1588
1589         IpAddress gatewayIp = subnetOpt.get().getGatewayIp();
1590         if (gatewayIp == null) {
1591             LOG.warn("getSubnetGwMac : No GW ip found for subnet {}", subnetId.getValue());
1592             return null;
1593         }
1594
1595         if (null != gatewayIp.getIpv6Address()) {
1596             return null;
1597         }
1598
1599         InstanceIdentifier<VpnPortipToPort> portIpInst = InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
1600             .child(VpnPortipToPort.class, new VpnPortipToPortKey(gatewayIp.getIpv4Address().getValue(), vpnName))
1601             .build();
1602         Optional<VpnPortipToPort> portIpToPortOpt =
1603                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1604                         LogicalDatastoreType.CONFIGURATION, portIpInst);
1605         if (portIpToPortOpt.isPresent()) {
1606             return portIpToPortOpt.get().getMacAddress();
1607         }
1608
1609         InstanceIdentifier<LearntVpnVipToPort> learntIpInst = InstanceIdentifier.builder(LearntVpnVipToPortData.class)
1610             .child(LearntVpnVipToPort.class, new LearntVpnVipToPortKey(gatewayIp.getIpv4Address().getValue(), vpnName))
1611             .build();
1612         Optional<LearntVpnVipToPort> learntIpToPortOpt =
1613                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1614                         LogicalDatastoreType.OPERATIONAL, learntIpInst);
1615         if (learntIpToPortOpt.isPresent()) {
1616             return learntIpToPortOpt.get().getMacAddress();
1617         }
1618
1619         LOG.info("getSubnetGwMac : No resolution was found to GW ip {} in subnet {}", gatewayIp, subnetId.getValue());
1620         return null;
1621     }
1622
1623     public static boolean isIPv6Subnet(String prefix) {
1624         return IpPrefixBuilder.getDefaultInstance(prefix).getIpv6Prefix() != null;
1625     }
1626
1627     static InstanceIdentifier<DpnRoutersList> getDpnRoutersId(BigInteger dpnId) {
1628         return InstanceIdentifier.builder(DpnRouters.class)
1629             .child(DpnRoutersList.class, new DpnRoutersListKey(dpnId)).build();
1630     }
1631
1632     static InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1633         return InstanceIdentifier.builder(NeutronRouterDpns.class)
1634             .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1635             .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1636     }
1637
1638     static InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1639         return InstanceIdentifier.builder(NeutronRouterDpns.class)
1640             .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1641     }
1642
1643     @Nullable
1644     protected static String getFloatingIpPortMacFromFloatingIpId(DataBroker broker, Uuid floatingIpId) {
1645         InstanceIdentifier<FloatingIpIdToPortMapping> id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
1646         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1647                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
1648                 FloatingIpIdToPortMapping::getFloatingIpPortMacAddress).orElse(null);
1649     }
1650
1651     @Nullable
1652     protected static String getFloatingIpPortMacFromFloatingIpId(TypedReadTransaction<Configuration> confTx,
1653         Uuid floatingIpId) {
1654         try {
1655             return confTx.read(buildfloatingIpIdToPortMappingIdentifier(floatingIpId)).get().toJavaUtil().map(
1656                 FloatingIpIdToPortMapping::getFloatingIpPortMacAddress).orElse(null);
1657         } catch (InterruptedException | ExecutionException e) {
1658             LOG.error("Error reading the floating IP port MAC for {}", floatingIpId, e);
1659             return null;
1660         }
1661     }
1662
1663     @Nullable
1664     protected static Uuid getFloatingIpPortSubnetIdFromFloatingIpId(DataBroker broker, Uuid floatingIpId) {
1665         InstanceIdentifier<FloatingIpIdToPortMapping> id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
1666         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1667                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
1668                 FloatingIpIdToPortMapping::getFloatingIpPortSubnetId).orElse(null);
1669     }
1670
1671     @Nullable
1672     protected static Uuid getFloatingIpPortSubnetIdFromFloatingIpId(TypedReadTransaction<Configuration> confTx,
1673         Uuid floatingIpId) {
1674         try {
1675             return confTx.read(buildfloatingIpIdToPortMappingIdentifier(floatingIpId)).get().toJavaUtil().map(
1676                 FloatingIpIdToPortMapping::getFloatingIpPortSubnetId).orElse(null);
1677         } catch (InterruptedException | ExecutionException e) {
1678             LOG.error("Error reading the floating IP port subnet for {}", floatingIpId, e);
1679             return null;
1680         }
1681     }
1682
1683     static InstanceIdentifier<FloatingIpIdToPortMapping> buildfloatingIpIdToPortMappingIdentifier(Uuid floatingIpId) {
1684         return InstanceIdentifier.builder(FloatingIpPortInfo.class).child(FloatingIpIdToPortMapping.class, new
1685             FloatingIpIdToPortMappingKey(floatingIpId)).build();
1686     }
1687
1688     @Nullable
1689     static Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
1690         InstanceIdentifier<Interface> ifStateId =
1691             buildStateInterfaceId(interfaceName);
1692         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1693                 LogicalDatastoreType.OPERATIONAL, ifStateId).orNull();
1694     }
1695
1696     static InstanceIdentifier<Interface> buildStateInterfaceId(String interfaceName) {
1697         InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
1698             InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
1699                 .interfaces.rev140508.InterfacesState.class)
1700                 .child(Interface.class,
1701                     new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
1702                         .interfaces.state.InterfaceKey(interfaceName));
1703         return idBuilder.build();
1704     }
1705
1706     @Nullable
1707     public static Routers getRoutersFromConfigDS(DataBroker dataBroker, String routerName) {
1708         InstanceIdentifier<Routers> routerIdentifier = NatUtil.buildRouterIdentifier(routerName);
1709         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1710                 LogicalDatastoreType.CONFIGURATION, routerIdentifier).orNull();
1711     }
1712
1713     @Nullable
1714     public static Routers getRoutersFromConfigDS(TypedReadTransaction<Configuration> confTx, String routerName) {
1715         try {
1716             return confTx.read(NatUtil.buildRouterIdentifier(routerName)).get().orNull();
1717         } catch (InterruptedException | ExecutionException e) {
1718             LOG.error("Error reading router {}", routerName, e);
1719             return null;
1720         }
1721     }
1722
1723     static void createRouterIdsConfigDS(DataBroker dataBroker, long routerId, String routerName) {
1724         if (routerId == NatConstants.INVALID_ID) {
1725             LOG.error("createRouterIdsConfigDS : invalid routerId for routerName {}", routerName);
1726             return;
1727         }
1728         RouterIds rtrs = new RouterIdsBuilder().withKey(new RouterIdsKey(routerId))
1729             .setRouterId(routerId).setRouterName(routerName).build();
1730         MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, buildRouterIdentifier(routerId), rtrs);
1731     }
1732
1733     @Nullable
1734     static FlowEntity buildDefaultNATFlowEntityForExternalSubnet(BigInteger dpId, long vpnId, String subnetId,
1735             IdManagerService idManager) {
1736         InetAddress defaultIP = null;
1737         try {
1738             defaultIP = InetAddress.getByName("0.0.0.0");
1739         } catch (UnknownHostException e) {
1740             LOG.error("buildDefaultNATFlowEntityForExternalSubnet : Failed to build FIB Table Flow for "
1741                     + "Default Route to NAT.", e);
1742             return null;
1743         }
1744
1745         List<MatchInfo> matches = new ArrayList<>();
1746         matches.add(MatchEthernetType.IPV4);
1747         //add match for vrfid
1748         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
1749
1750         List<InstructionInfo> instructions = new ArrayList<>();
1751         List<ActionInfo> actionsInfo = new ArrayList<>();
1752         long groupId = getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME, NatUtil.getGroupIdKey(subnetId));
1753         if (groupId == NatConstants.INVALID_ID) {
1754             LOG.error("Unable to get groupId for subnet {} while building defauly flow entity", subnetId);
1755             return null;
1756         }
1757         actionsInfo.add(new ActionGroup(groupId));
1758         String flowRef = getFlowRef(dpId, NwConstants.L3_FIB_TABLE, defaultIP, vpnId);
1759         instructions.add(new InstructionApplyActions(actionsInfo));
1760         return MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_FIB_TABLE, flowRef,
1761                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
1762                 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
1763     }
1764
1765     @Nullable
1766     static String getExtGwMacAddFromRouterId(DataBroker broker, long routerId) {
1767         String routerName = getRouterName(broker, routerId);
1768         if (routerName == null) {
1769             LOG.error("getExtGwMacAddFromRouterId : empty routerName received");
1770             return null;
1771         }
1772         return getExtGwMacAddFromRouterName(broker, routerName);
1773     }
1774
1775     @Nullable
1776     static String getExtGwMacAddFromRouterName(DataBroker broker, String routerName) {
1777         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerName);
1778         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1779                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(Routers::getExtGwMacAddress).orElse(null);
1780     }
1781
1782     @Nullable
1783     static String getExtGwMacAddFromRouterName(TypedReadTransaction<Configuration> tx, String routerName) {
1784         try {
1785             return tx.read(buildRouterIdentifier(routerName)).get().toJavaUtil().map(
1786                 Routers::getExtGwMacAddress).orElse(null);
1787         } catch (InterruptedException | ExecutionException e) {
1788             LOG.error("Error retrieving external gateway MAC address for router {}", routerName, e);
1789             return null;
1790         }
1791     }
1792
1793     static InstanceIdentifier<Router> buildNeutronRouterIdentifier(Uuid routerUuid) {
1794         InstanceIdentifier<Router> routerInstanceIdentifier = InstanceIdentifier.create(Neutron.class)
1795              .child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers.class)
1796              .child(Router.class, new RouterKey(routerUuid));
1797         return routerInstanceIdentifier;
1798     }
1799
1800     @Nullable
1801     public static String getNeutronRouterNamebyUuid(DataBroker broker, Uuid routerUuid) {
1802         InstanceIdentifier<Router> neutronRouterIdentifier = NatUtil.buildNeutronRouterIdentifier(routerUuid);
1803         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1804                 LogicalDatastoreType.CONFIGURATION, neutronRouterIdentifier).toJavaUtil().map(Router::getName).orElse(
1805                 null);
1806     }
1807
1808     @NonNull
1809     public static List<Ports> getFloatingIpPortsForRouter(DataBroker broker, Uuid routerUuid) {
1810         InstanceIdentifier<RouterPorts> routerPortsIdentifier = getRouterPortsId(routerUuid.getValue());
1811         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1812                 LogicalDatastoreType.CONFIGURATION,
1813                 routerPortsIdentifier).toJavaUtil().map(RouterPorts::getPorts).orElse(emptyList());
1814     }
1815
1816     @NonNull
1817     public static List<Uuid> getRouterUuIdsForVpn(DataBroker broker, Uuid vpnUuid) {
1818         InstanceIdentifier<ExternalNetworks> externalNwIdentifier = InstanceIdentifier.create(ExternalNetworks.class);
1819         Optional<ExternalNetworks> externalNwData =
1820                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1821                         LogicalDatastoreType.CONFIGURATION, externalNwIdentifier);
1822         if (externalNwData.isPresent()) {
1823             for (Networks externalNw : externalNwData.get().nonnullNetworks()) {
1824                 if (externalNw.getVpnid() != null && externalNw.getVpnid().equals(vpnUuid)) {
1825                     @Nullable List<Uuid> routerIds = externalNw.getRouterIds();
1826                     return routerIds != null ? routerIds : emptyList();
1827                 }
1828             }
1829         }
1830         return emptyList();
1831     }
1832
1833     public static boolean isIpInSubnet(String ipAddress, String start, String end) {
1834
1835         try {
1836             long ipLo = ipToLong(InetAddress.getByName(start));
1837             long ipHi = ipToLong(InetAddress.getByName(end));
1838             long ipToTest = ipToLong(InetAddress.getByName(ipAddress));
1839             return ipToTest >= ipLo && ipToTest <= ipHi;
1840         } catch (UnknownHostException e) {
1841             LOG.error("isIpInSubnet : failed for IP {}", ipAddress, e);
1842             return false;
1843         }
1844     }
1845
1846     @NonNull
1847     public static Collection<Uuid> getExternalSubnetIdsFromExternalIps(@Nullable List<ExternalIps> externalIps) {
1848         if (externalIps == null) {
1849             return Collections.emptySet();
1850         }
1851
1852         return externalIps.stream().map(ExternalIps::getSubnetId).collect(Collectors.toSet());
1853     }
1854
1855     @NonNull
1856     public static Collection<Uuid> getExternalSubnetIdsForRouter(DataBroker dataBroker, @Nullable String routerName) {
1857         if (routerName == null) {
1858             LOG.error("getExternalSubnetIdsForRouter : empty routerName received");
1859             return Collections.emptySet();
1860         }
1861
1862         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerName);
1863         Optional<Routers> routerData =
1864                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1865                         LogicalDatastoreType.CONFIGURATION, id);
1866         if (routerData.isPresent()) {
1867             return NatUtil.getExternalSubnetIdsFromExternalIps(routerData.get().getExternalIps());
1868         } else {
1869             LOG.warn("getExternalSubnetIdsForRouter : No external router data for router {}", routerName);
1870             return Collections.emptySet();
1871         }
1872     }
1873
1874     @NonNull
1875     protected static Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
1876         .subnets.Subnets> getOptionalExternalSubnets(DataBroker dataBroker, Uuid subnetId) {
1877         if (subnetId == null) {
1878             LOG.warn("getOptionalExternalSubnets : subnetId is null");
1879             return Optional.absent();
1880         }
1881
1882         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice
1883             .rev160111.external.subnets.Subnets> subnetsIdentifier =
1884                 InstanceIdentifier.builder(ExternalSubnets.class)
1885                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice
1886                         .rev160111.external.subnets.Subnets.class, new SubnetsKey(subnetId)).build();
1887         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1888                 LogicalDatastoreType.CONFIGURATION, subnetsIdentifier);
1889     }
1890
1891     @NonNull
1892     protected static Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
1893         .subnets.Subnets> getOptionalExternalSubnets(TypedReadTransaction<Configuration> tx, Uuid subnetId) {
1894         if (subnetId == null) {
1895             LOG.warn("getOptionalExternalSubnets : subnetId is null");
1896             return Optional.absent();
1897         }
1898
1899         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice
1900             .rev160111.external.subnets.Subnets> subnetsIdentifier =
1901             InstanceIdentifier.builder(ExternalSubnets.class)
1902                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice
1903                     .rev160111.external.subnets.Subnets.class, new SubnetsKey(subnetId)).build();
1904         try {
1905             return tx.read(subnetsIdentifier).get();
1906         } catch (InterruptedException | ExecutionException e) {
1907             LOG.error("Error retrieving external subnets on {}", subnetId, e);
1908             return Optional.absent();
1909         }
1910     }
1911
1912     protected static long getExternalSubnetVpnId(DataBroker dataBroker, Uuid subnetId) {
1913         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
1914             .subnets.Subnets> optionalExternalSubnets = NatUtil.getOptionalExternalSubnets(dataBroker,
1915                    subnetId);
1916         if (optionalExternalSubnets.isPresent()) {
1917             return NatUtil.getVpnId(dataBroker, subnetId.getValue());
1918         }
1919
1920         return NatConstants.INVALID_ID;
1921     }
1922
1923     protected static long getExternalSubnetVpnId(TypedReadTransaction<Configuration> tx, Uuid subnetId) {
1924         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
1925             .subnets.Subnets> optionalExternalSubnets = NatUtil.getOptionalExternalSubnets(tx,
1926             subnetId);
1927         if (optionalExternalSubnets.isPresent()) {
1928             return NatUtil.getVpnId(tx, subnetId.getValue());
1929         }
1930
1931         return NatConstants.INVALID_ID;
1932     }
1933
1934     protected static long getExternalSubnetVpnIdForRouterExternalIp(DataBroker dataBroker, String externalIpAddress,
1935             Routers router) {
1936         Uuid externalSubnetId = NatUtil.getExternalSubnetForRouterExternalIp(externalIpAddress, router);
1937         if (externalSubnetId != null) {
1938             return NatUtil.getExternalSubnetVpnId(dataBroker,externalSubnetId);
1939         }
1940
1941         return NatConstants.INVALID_ID;
1942     }
1943
1944     @Nullable
1945     protected static Uuid getExternalSubnetForRouterExternalIp(String externalIpAddress, Routers router) {
1946         externalIpAddress = validateAndAddNetworkMask(externalIpAddress);
1947         for (ExternalIps extIp : router.nonnullExternalIps()) {
1948             String extIpString = validateAndAddNetworkMask(extIp.getIpAddress());
1949             if (extIpString.equals(externalIpAddress)) {
1950                 return extIp.getSubnetId();
1951             }
1952         }
1953         LOG.warn("getExternalSubnetForRouterExternalIp : Missing External Subnet for Ip:{}", externalIpAddress);
1954         return null;
1955     }
1956
1957     private static long ipToLong(InetAddress ip) {
1958         byte[] octets = ip.getAddress();
1959         long result = 0;
1960         for (byte octet : octets) {
1961             result <<= 8;
1962             result |= octet & 0xff;
1963         }
1964         return result;
1965     }
1966
1967     @NonNull
1968     static List<String> getIpsListFromExternalIps(@Nullable List<ExternalIps> externalIps) {
1969         if (externalIps == null) {
1970             return emptyList();
1971         }
1972
1973         return externalIps.stream().map(ExternalIps::getIpAddress).collect(Collectors.toList());
1974     }
1975
1976     // elan-instances config container
1977     @Nullable
1978     public static ElanInstance getElanInstanceByName(String elanInstanceName, DataBroker broker) {
1979         InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
1980         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1981                 LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orNull();
1982     }
1983
1984     @Nullable
1985     public static ElanInstance getElanInstanceByName(TypedReadTransaction<Configuration> tx, String elanInstanceName) {
1986         try {
1987             return tx.read(getElanInstanceConfigurationDataPath(elanInstanceName)).get().orNull();
1988         } catch (InterruptedException | ExecutionException e) {
1989             LOG.error("Error retrieving ELAN instance by name {}", elanInstanceName, e);
1990             return null;
1991         }
1992     }
1993
1994     public static InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
1995         return InstanceIdentifier.builder(ElanInstances.class)
1996                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
1997     }
1998
1999     public static long getTunnelIdForNonNaptToNaptFlow(DataBroker dataBroker, NatOverVxlanUtil natOverVxlanUtil,
2000                                                        IElanService elanManager, IdManagerService idManager,
2001                                                        long routerId, String routerName) {
2002         if (elanManager.isOpenStackVniSemanticsEnforced()) {
2003             // Router VNI will be set as tun_id if OpenStackSemantics is enabled
2004             return natOverVxlanUtil.getRouterVni(routerName, routerId).longValue();
2005         } else {
2006             return NatEvpnUtil.getTunnelIdForRouter(idManager, dataBroker, routerName, routerId);
2007         }
2008     }
2009
2010     public static void makePreDnatToSnatTableEntry(IMdsalApiManager mdsalManager, BigInteger naptDpnId,
2011             short tableId, TypedWriteTransaction<Configuration> confTx) {
2012         LOG.debug("makePreDnatToSnatTableEntry : Create Pre-DNAT table {} --> table {} flow on NAPT DpnId {} ",
2013                 NwConstants.PDNAT_TABLE, tableId, naptDpnId);
2014
2015         List<Instruction> preDnatToSnatInstructions = new ArrayList<>();
2016         preDnatToSnatInstructions.add(new InstructionGotoTable(tableId).buildInstruction(0));
2017         List<MatchInfo> matches = new ArrayList<>();
2018         matches.add(MatchEthernetType.IPV4);
2019         String flowRef = getFlowRefPreDnatToSnat(naptDpnId, NwConstants.PDNAT_TABLE, "PreDNATToSNAT");
2020         Flow preDnatToSnatTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.PDNAT_TABLE,flowRef,
2021                 5, flowRef, 0, 0,  NwConstants.COOKIE_DNAT_TABLE,
2022                 matches, preDnatToSnatInstructions);
2023
2024         mdsalManager.addFlow(confTx, naptDpnId, preDnatToSnatTableFlowEntity);
2025         LOG.debug("makePreDnatToSnatTableEntry : Successfully installed Pre-DNAT flow {} on NAPT DpnId {} ",
2026                 preDnatToSnatTableFlowEntity,  naptDpnId);
2027     }
2028
2029     public static void removePreDnatToSnatTableEntry(TypedReadWriteTransaction<Configuration> confTx,
2030             IMdsalApiManager mdsalManager, BigInteger naptDpnId) throws ExecutionException, InterruptedException {
2031         LOG.debug("removePreDnatToSnatTableEntry : Remove Pre-DNAT table {} --> table {} flow on NAPT DpnId {} ",
2032                 NwConstants.PDNAT_TABLE, NwConstants.INBOUND_NAPT_TABLE, naptDpnId);
2033         String flowRef = getFlowRefPreDnatToSnat(naptDpnId, NwConstants.PDNAT_TABLE, "PreDNATToSNAT");
2034         mdsalManager.removeFlow(confTx, naptDpnId, flowRef, NwConstants.PDNAT_TABLE);
2035         LOG.debug("removePreDnatToSnatTableEntry: Successfully removed Pre-DNAT flow {} on NAPT DpnId = {}",
2036                 flowRef, naptDpnId);
2037     }
2038
2039     private static String getFlowRefPreDnatToSnat(BigInteger dpnId, short tableId, String uniqueId) {
2040         return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId
2041                 + NwConstants.FLOWID_SEPARATOR + uniqueId;
2042     }
2043
2044     public static boolean isFloatingIpPresentForDpn(DataBroker dataBroker, BigInteger dpnId, String rd,
2045                                                     String vpnName, String externalIp,
2046                                                     Boolean isMoreThanOneFipCheckOnDpn) {
2047         InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
2048         Optional<VpnToDpnList> dpnInVpn = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
2049         if (dpnInVpn.isPresent()) {
2050             LOG.debug("isFloatingIpPresentForDpn : vpn-to-dpn-list is not empty for vpnName {}, dpn id {}, "
2051                     + "rd {} and floatingIp {}", vpnName, dpnId, rd, externalIp);
2052             try {
2053                 List<IpAddresses> ipAddressList = dpnInVpn.get().getIpAddresses();
2054                 if (ipAddressList != null && !ipAddressList.isEmpty()) {
2055                     int floatingIpPresentCount = 0;
2056                     for (IpAddresses ipAddress: ipAddressList) {
2057                         if (!Objects.equals(ipAddress.getIpAddress(), externalIp)
2058                                 && IpAddresses.IpAddressSource.FloatingIP.equals(ipAddress.getIpAddressSource())) {
2059                             floatingIpPresentCount++;
2060                             //Add tunnel table check
2061                             if (isMoreThanOneFipCheckOnDpn && floatingIpPresentCount > 1) {
2062                                 return true;
2063                             }
2064                             //Remove tunnel table check
2065                             if (!isMoreThanOneFipCheckOnDpn) {
2066                                 return true;
2067                             }
2068                         }
2069                     }
2070                 } else {
2071                     LOG.debug("isFloatingIpPresentForDpn : vpn-to-dpn-list does not contain any floating IP for DPN {}",
2072                            dpnId);
2073                     return false;
2074                 }
2075             } catch (NullPointerException e) {
2076                 LOG.error("isFloatingIpPresentForDpn: Exception occurred on getting external IP address from "
2077                         + "vpn-to-dpn-list on Dpn {}", dpnId, e);
2078                 return false;
2079             }
2080         }
2081         return false;
2082     }
2083
2084     private static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
2085         return InstanceIdentifier.builder(VpnInstanceOpData.class)
2086                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd))
2087                 .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
2088     }
2089
2090     @Nullable
2091     public static String getPrimaryRd(String vpnName, TypedReadTransaction<Configuration> tx)
2092         throws ExecutionException, InterruptedException {
2093         return tx.read(getVpnInstanceIdentifier(vpnName)).get().toJavaUtil().map(NatUtil::getPrimaryRd).orElse(null);
2094     }
2095
2096     @Nullable
2097     public static String getPrimaryRd(@Nullable VpnInstance vpnInstance) {
2098         if (vpnInstance == null) {
2099             return null;
2100         }
2101         List<String> rds = getListOfRdsFromVpnInstance(vpnInstance);
2102         return rds.isEmpty() ? vpnInstance.getVpnInstanceName() : rds.get(0);
2103     }
2104
2105     public static InstanceIdentifier<VpnInstance> getVpnInstanceIdentifier(String vpnName) {
2106         return InstanceIdentifier.builder(VpnInstances.class)
2107             .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
2108     }
2109
2110     @NonNull
2111     public static List<String> getListOfRdsFromVpnInstance(VpnInstance vpnInstance) {
2112         VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
2113         return vpnConfig.getRouteDistinguisher() != null ? new ArrayList<>(
2114                 vpnConfig.getRouteDistinguisher()) : new ArrayList<>();
2115     }
2116
2117     public static String validateAndAddNetworkMask(String ipAddress) {
2118         return ipAddress.contains("/32") ? ipAddress : ipAddress + "/32";
2119     }
2120
2121     public static InstanceIdentifier<VpnInterfaceOpDataEntry> getVpnInterfaceOpDataEntryIdentifier(
2122             String vpnInterfaceName, String vpnName) {
2123         return InstanceIdentifier.builder(VpnInterfaceOpData.class).child(VpnInterfaceOpDataEntry.class,
2124         new VpnInterfaceOpDataEntryKey(vpnInterfaceName, vpnName)).build();
2125     }
2126
2127     public static boolean checkForRoutersWithSameExtNetAndNaptSwitch(DataBroker broker, Uuid networkId,
2128                                                                      String routerName, BigInteger dpnId) {
2129         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
2130         Optional<Networks> networkData = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
2131
2132         if (networkData != null && networkData.isPresent()) {
2133             List<Uuid> routerUuidList = networkData.get().getRouterIds();
2134             if (routerUuidList != null && !routerUuidList.isEmpty()) {
2135                 for (Uuid routerUuid : routerUuidList) {
2136                     String sharedRouterName = routerUuid.getValue();
2137                     if (!routerName.equals(sharedRouterName)) {
2138                         BigInteger switchDpnId = NatUtil.getPrimaryNaptfromRouterName(broker, sharedRouterName);
2139                         if (switchDpnId != null && switchDpnId.equals(dpnId)) {
2140                             LOG.debug("checkForRoutersWithSameExtNetAndNaptSwitch: external-network {} is "
2141                                     + "associated with other active router {} on NAPT switch {}", networkId,
2142                                     sharedRouterName, switchDpnId);
2143                             return true;
2144                         }
2145                     }
2146                 }
2147             }
2148         }
2149         return false;
2150     }
2151
2152     public static boolean checkForRoutersWithSameExtSubnetAndNaptSwitch(DataBroker broker, Uuid externalSubnetId,
2153                                                                         String routerName, BigInteger dpnId) {
2154         List<Uuid> routerUuidList = getOptionalExternalSubnets(broker, externalSubnetId).toJavaUtil()
2155             .map(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
2156                 .subnets.Subnets::getRouterIds).orElse(emptyList());
2157         if (!routerUuidList.isEmpty()) {
2158             for (Uuid routerUuid : routerUuidList) {
2159                 String sharedRouterName = routerUuid.getValue();
2160                 if (!routerName.equals(sharedRouterName)) {
2161                     BigInteger switchDpnId = NatUtil.getPrimaryNaptfromRouterName(broker, sharedRouterName);
2162                     if (switchDpnId != null && switchDpnId.equals(dpnId)) {
2163                         LOG.debug("checkForRoutersWithSameExtSubnetAndNaptSwitch: external-subnetwork {} is "
2164                                   + "associated with other active router {} on NAPT switch {}", externalSubnetId,
2165                             sharedRouterName, switchDpnId);
2166                         return true;
2167                     }
2168                 }
2169             }
2170         }
2171         return false;
2172     }
2173
2174     public static void installRouterGwFlows(ManagedNewTransactionRunner txRunner, IVpnManager vpnManager,
2175             Routers router, BigInteger primarySwitchId, int addOrRemove) {
2176         ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
2177             List<ExternalIps> externalIps = router.getExternalIps();
2178             List<String> externalIpsSting = new ArrayList<>();
2179
2180             if (externalIps == null || externalIps.isEmpty()) {
2181                 LOG.error("installRouterGwFlows: setupRouterGwFlows no externalIP present");
2182                 return;
2183             }
2184             for (ExternalIps externalIp : externalIps) {
2185                 externalIpsSting.add(externalIp.getIpAddress());
2186             }
2187             Uuid subnetVpnName = externalIps.get(0).getSubnetId();
2188             if (addOrRemove == NwConstants.ADD_FLOW) {
2189                 vpnManager.addRouterGwMacFlow(router.getRouterName(), router.getExtGwMacAddress(), primarySwitchId,
2190                         router.getNetworkId(), subnetVpnName.getValue(), tx);
2191                 vpnManager.addArpResponderFlowsToExternalNetworkIps(router.getRouterName(), externalIpsSting,
2192                         router.getExtGwMacAddress(), primarySwitchId,
2193                         router.getNetworkId());
2194             } else {
2195                 vpnManager.removeRouterGwMacFlow(router.getRouterName(), router.getExtGwMacAddress(), primarySwitchId,
2196                         router.getNetworkId(), subnetVpnName.getValue(), tx);
2197                 vpnManager.removeArpResponderFlowsToExternalNetworkIps(router.getRouterName(), externalIpsSting,
2198                         router.getExtGwMacAddress(), primarySwitchId,
2199                         router.getNetworkId());
2200             }
2201         }), LOG, "Error installing router gateway flows");
2202     }
2203
2204     @SuppressWarnings("checkstyle:IllegalCatch")
2205     public static void handleSNATForDPN(DataBroker dataBroker, IMdsalApiManager mdsalManager,
2206         IdManagerService idManager, NaptSwitchHA naptSwitchHA,
2207         BigInteger dpnId, Routers extRouters, long routerId, Long routerVpnId,
2208         TypedReadWriteTransaction<Configuration> confTx,
2209         ProviderTypes extNwProvType, UpgradeState upgradeState) {
2210         //Check if primary and secondary switch are selected, If not select the role
2211         //Install select group to NAPT switch
2212         //Install default miss entry to NAPT switch
2213         BigInteger naptSwitch;
2214         String routerName = extRouters.getRouterName();
2215         Boolean upgradeInProgress = false;
2216         if (upgradeState != null) {
2217             upgradeInProgress = upgradeState.isUpgradeInProgress();
2218         }
2219         BigInteger naptId = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
2220         if (naptId == null || naptId.equals(BigInteger.ZERO)
2221             || (!NatUtil.getSwitchStatus(dataBroker, naptId) && (upgradeInProgress == false))) {
2222             LOG.debug("handleSNATForDPN : NaptSwitch is down or not selected for router {},naptId {}",
2223                 routerName, naptId);
2224             naptSwitch = dpnId;
2225             boolean naptstatus = naptSwitchHA.updateNaptSwitch(routerName, naptSwitch);
2226             if (!naptstatus) {
2227                 LOG.error("handleSNATForDPN : Failed to update newNaptSwitch {} for routername {}",
2228                     naptSwitch, routerName);
2229                 return;
2230             }
2231             LOG.debug("handleSNATForDPN : Switch {} is elected as NaptSwitch for router {}", dpnId, routerName);
2232
2233             String externalVpnName = null;
2234             NatUtil.createRouterIdsConfigDS(dataBroker, routerId, routerName);
2235             naptSwitchHA.subnetRegisterMapping(extRouters, routerId);
2236             Uuid extNwUuid = extRouters.getNetworkId();
2237             externalVpnName = NatUtil.getAssociatedVPN(dataBroker, extNwUuid);
2238             if (externalVpnName != null) {
2239                 naptSwitchHA.installSnatFlows(routerName, routerId, naptSwitch, routerVpnId, extNwUuid,
2240                     externalVpnName, confTx);
2241             }
2242             // Install miss entry (table 26) pointing to table 46
2243             FlowEntity flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName,
2244                 routerVpnId, NatConstants.ADD_FLOW);
2245             if (flowEntity == null) {
2246                 LOG.error("handleSNATForDPN : Failed to populate flowentity for router {} with dpnId {}",
2247                     routerName, dpnId);
2248                 return;
2249             }
2250             LOG.debug("handleSNATForDPN : Successfully installed flow for dpnId {} router {}", dpnId, routerName);
2251             mdsalManager.addFlow(confTx, flowEntity);
2252             //Removing primary flows from old napt switch
2253             if (naptId != null && !naptId.equals(BigInteger.ZERO)) {
2254                 LOG.debug("handleSNATForDPN : Removing primary flows from old napt switch {} for router {}",
2255                     naptId, routerName);
2256                 try {
2257                     naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptId, null,
2258                         externalVpnName, confTx);
2259                 } catch (Exception e) {
2260                     LOG.error("Exception while removing SnatFlows form OldNaptSwitch {}", naptId, e);
2261                 }
2262             }
2263             naptSwitchHA.updateNaptSwitchBucketStatus(routerName, routerId, naptSwitch);
2264         } else if (naptId.equals(dpnId)) {
2265             LOG.error("handleSNATForDPN : NaptSwitch {} gone down during cluster reboot came alive", naptId);
2266         } else {
2267             naptSwitch = naptId;
2268             LOG.debug("handleSNATForDPN : Napt switch with Id {} is already elected for router {}",
2269                 naptId, routerName);
2270
2271             //installing group
2272             List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInNeighborSwitches(dpnId,
2273                 routerName, routerId, naptSwitch);
2274             naptSwitchHA.installSnatGroupEntry(dpnId, bucketInfo, routerName);
2275
2276             // Install miss entry (table 26) pointing to group
2277             long groupId = NatUtil.getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME,
2278                 NatUtil.getGroupIdKey(routerName));
2279             if (groupId != NatConstants.INVALID_ID) {
2280                 FlowEntity flowEntity =
2281                     naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,
2282                         routerVpnId, NatConstants.ADD_FLOW);
2283                 if (flowEntity == null) {
2284                     LOG.error("handleSNATForDPN : Failed to populate flowentity for router {} with dpnId {}"
2285                         + " groupId {}", routerName, dpnId, groupId);
2286                     return;
2287                 }
2288                 LOG.debug("handleSNATForDPN : Successfully installed flow for dpnId {} router {} group {}",
2289                     dpnId, routerName, groupId);
2290                 mdsalManager.addFlow(confTx, flowEntity);
2291             } else {
2292                 LOG.error("handleSNATForDPN: Unable to get groupId for router:{}", routerName);
2293             }
2294         }
2295     }
2296
2297     @SuppressWarnings("checkstyle:IllegalCatch")
2298     public static void removeSNATFromDPN(DataBroker dataBroker, IMdsalApiManager mdsalManager,
2299             IdManagerService idManager, NaptSwitchHA naptSwitchHA, BigInteger dpnId,
2300             String routerName, long routerId, long routerVpnId, Uuid extNetworkId,
2301             ProviderTypes extNwProvType, TypedReadWriteTransaction<Configuration> confTx)
2302                     throws ExecutionException, InterruptedException {
2303         //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
2304         //remove miss entry to NAPT switch
2305         //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
2306         if (extNwProvType == null) {
2307             return;
2308         }
2309         //Get the external IP labels other than VXLAN provider type. Since label is not applicable for VXLAN
2310         Map<String, Long> externalIpLabel;
2311         if (extNwProvType == ProviderTypes.VXLAN) {
2312             externalIpLabel = null;
2313         } else {
2314             externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
2315         }
2316         BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
2317         if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
2318             LOG.error("removeSNATFromDPN : No naptSwitch is selected for router {}", routerName);
2319             return;
2320         }
2321         Collection<String> externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
2322         boolean naptStatus =
2323             naptSwitchHA.isNaptSwitchDown(routerName, routerId, dpnId, naptSwitch, routerVpnId,
2324                     externalIpCache, confTx);
2325         if (!naptStatus) {
2326             LOG.debug("removeSNATFromDPN: Switch with DpnId {} is not naptSwitch for router {}",
2327                 dpnId, routerName);
2328             long groupId = getUniqueId(idManager, NatConstants.SNAT_IDPOOL_NAME, NatUtil.getGroupIdKey(routerName));
2329             FlowEntity flowEntity = null;
2330             try {
2331                 if (groupId != NatConstants.INVALID_ID) {
2332                     flowEntity = naptSwitchHA
2333                         .buildSnatFlowEntity(dpnId, routerName, groupId, routerVpnId,
2334                             NatConstants.DEL_FLOW);
2335                     if (flowEntity == null) {
2336                         LOG.error("removeSNATFromDPN : Failed to populate flowentity for router:{} "
2337                             + "with dpnId:{} groupId:{}", routerName, dpnId, groupId);
2338                         return;
2339                     }
2340                     LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity {}",
2341                         flowEntity);
2342                     mdsalManager.removeFlow(confTx, flowEntity);
2343                 } else {
2344                     LOG.error("removeSNATFromDPN: Unable to get groupId for router:{}", routerName);
2345                 }
2346
2347             } catch (Exception ex) {
2348                 LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
2349                     flowEntity, ex);
2350                 return;
2351             }
2352             LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}",
2353                 dpnId, routerName);
2354
2355             //remove group
2356             GroupEntity groupEntity = null;
2357             try {
2358                 if (groupId != NatConstants.INVALID_ID) {
2359                     groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
2360                         GroupTypes.GroupAll, emptyList() /*listBucketInfo*/);
2361                     LOG.info("removeSNATFromDPN : Removing NAPT GroupEntity:{}", groupEntity);
2362                     mdsalManager.removeGroup(groupEntity);
2363                 } else {
2364                     LOG.error("removeSNATFromDPN: Unable to get groupId for router:{}", routerName);
2365                 }
2366             } catch (Exception ex) {
2367                 LOG.error("removeSNATFromDPN : Failed to remove group entity {}", groupEntity, ex);
2368                 return;
2369             }
2370             LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routerName {}",
2371                 dpnId, routerName);
2372         } else {
2373             String externalVpnName = NatUtil.getAssociatedVPN(dataBroker, extNetworkId);
2374             naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptSwitch,
2375                     externalIpLabel, externalVpnName, confTx);
2376             //remove table 26 flow ppointing to table46
2377             FlowEntity flowEntity = null;
2378             try {
2379                 flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId,
2380                     NatConstants.DEL_FLOW);
2381                 if (flowEntity == null) {
2382                     LOG.error("removeSNATFromDPN : Failed to populate flowentity for router {} with dpnId {}",
2383                             routerName, dpnId);
2384                     return;
2385                 }
2386                 LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity for router {} with "
2387                     + "dpnId {} in napt switch {}", routerName, dpnId, naptSwitch);
2388                 mdsalManager.removeFlow(confTx, flowEntity);
2389
2390             } catch (Exception ex) {
2391                 LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
2392                     flowEntity, ex);
2393                 return;
2394             }
2395             LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}",
2396                 dpnId, routerName);
2397
2398             //best effort to check IntExt model
2399             naptSwitchHA.bestEffortDeletion(routerId, routerName, externalIpLabel, confTx);
2400         }
2401     }
2402
2403     public static Boolean isOpenStackVniSemanticsEnforcedForGreAndVxlan(IElanService elanManager,
2404                                                                         ProviderTypes extNwProvType) {
2405         if (elanManager.isOpenStackVniSemanticsEnforced() && (extNwProvType == ProviderTypes.GRE
2406                 || extNwProvType == ProviderTypes.VXLAN)) {
2407             return true;
2408         }
2409         return false;
2410     }
2411
2412     public static void addPseudoPortToElanDpn(String elanInstanceName, String pseudoPortId,
2413             BigInteger dpnId, DataBroker dataBroker) {
2414         InstanceIdentifier<DpnInterfaces> elanDpnInterfaceId = getElanDpnInterfaceOperationalDataPath(
2415                 elanInstanceName, dpnId);
2416         // FIXME: separate this out?
2417         final ReentrantLock lock = JvmGlobalLocks.getLockForString(elanInstanceName);
2418         lock.lock();
2419         try {
2420             Optional<DpnInterfaces> dpnInElanInterfaces = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2421                 LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
2422             List<String> elanInterfaceList;
2423             DpnInterfaces dpnInterface;
2424             if (!dpnInElanInterfaces.isPresent()) {
2425                 elanInterfaceList = new ArrayList<>();
2426             } else {
2427                 dpnInterface = dpnInElanInterfaces.get();
2428                 elanInterfaceList = dpnInterface.getInterfaces();
2429             }
2430             if (!elanInterfaceList.contains(pseudoPortId)) {
2431                 elanInterfaceList.add(pseudoPortId);
2432                 dpnInterface = new DpnInterfacesBuilder().setDpId(dpnId).setInterfaces(elanInterfaceList)
2433                         .withKey(new DpnInterfacesKey(dpnId)).build();
2434                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
2435                     elanDpnInterfaceId, dpnInterface);
2436             }
2437         } catch (ReadFailedException e) {
2438             LOG.warn("Failed to read elanDpnInterface with error {}", e.getMessage());
2439         } catch (TransactionCommitFailedException e) {
2440             LOG.warn("Failed to add elanDpnInterface with error {}", e.getMessage());
2441         } finally {
2442             lock.unlock();
2443         }
2444     }
2445
2446     public static void removePseudoPortFromElanDpn(String elanInstanceName, String pseudoPortId,
2447             BigInteger dpnId, DataBroker dataBroker) {
2448         InstanceIdentifier<DpnInterfaces> elanDpnInterfaceId = getElanDpnInterfaceOperationalDataPath(
2449                 elanInstanceName, dpnId);
2450         // FIXME: separate this out?
2451         final ReentrantLock lock = JvmGlobalLocks.getLockForString(elanInstanceName);
2452         lock.lock();
2453         try {
2454             Optional<DpnInterfaces> dpnInElanInterfaces = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2455                     LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
2456             List<String> elanInterfaceList;
2457             DpnInterfaces dpnInterface;
2458             if (!dpnInElanInterfaces.isPresent()) {
2459                 LOG.info("No interface in any dpn for {}", elanInstanceName);
2460                 return;
2461             }
2462
2463             dpnInterface = dpnInElanInterfaces.get();
2464             elanInterfaceList = dpnInterface.getInterfaces();
2465             if (!elanInterfaceList.contains(pseudoPortId)) {
2466                 LOG.info("Router port not present in DPN {} for VPN {}", dpnId, elanInstanceName);
2467                 return;
2468             }
2469             elanInterfaceList.remove(pseudoPortId);
2470             dpnInterface = new DpnInterfacesBuilder().setDpId(dpnId).setInterfaces(elanInterfaceList)
2471                     .withKey(new DpnInterfacesKey(dpnId)).build();
2472             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
2473                     elanDpnInterfaceId, dpnInterface);
2474         } catch (ReadFailedException e) {
2475             LOG.warn("Failed to read elanDpnInterface with error {}", e.getMessage());
2476         } catch (TransactionCommitFailedException e) {
2477             LOG.warn("Failed to remove elanDpnInterface with error {}", e.getMessage());
2478         } finally {
2479             lock.unlock();
2480         }
2481     }
2482
2483     public static boolean isLastExternalRouter(String networkid, String routerName, NatDataUtil natDataUtil) {
2484         Set<Map.Entry<String,Routers>> extRouter = natDataUtil.getAllRouters();
2485         for (Map.Entry<String,Routers> router : extRouter) {
2486             if (!router.getKey().equals(routerName) && router.getValue().getNetworkId().getValue()
2487                     .equals(networkid)) {
2488                 return false;
2489             }
2490         }
2491         return true;
2492     }
2493
2494     @Nullable
2495     public static LearntVpnVipToPortData getLearntVpnVipToPortData(DataBroker dataBroker) {
2496         try {
2497             return SingleTransactionDataBroker.syncRead(dataBroker,
2498                     LogicalDatastoreType.OPERATIONAL, getLearntVpnVipToPortDataId());
2499         }
2500         catch (ReadFailedException e) {
2501             LOG.warn("Failed to read LearntVpnVipToPortData with error {}", e.getMessage());
2502             return null;
2503         }
2504     }
2505
2506     public static InstanceIdentifier<LearntVpnVipToPortData> getLearntVpnVipToPortDataId() {
2507         InstanceIdentifier<LearntVpnVipToPortData> learntVpnVipToPortDataId = InstanceIdentifier
2508                 .builder(LearntVpnVipToPortData.class).build();
2509         return learntVpnVipToPortDataId;
2510     }
2511
2512     public static InstanceIdentifier<DpnInterfaces> getElanDpnInterfaceOperationalDataPath(String elanInstanceName,
2513             BigInteger dpId) {
2514         return InstanceIdentifier.builder(ElanDpnInterfaces.class)
2515                 .child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName))
2516                 .child(DpnInterfaces.class, new DpnInterfacesKey(dpId)).build();
2517     }
2518
2519     public static InstanceIdentifier<Group> getGroupInstanceId(BigInteger dpnId, long groupId) {
2520         return InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight
2521                 .inventory.rev130819.nodes.Node.class, new NodeKey(new NodeId("openflow:" + dpnId)))
2522                 .augmentation(FlowCapableNode.class).child(Group.class, new GroupKey(new GroupId(groupId))).build();
2523     }
2524
2525     public static void createGroupIdPool(IdManagerService idManager) {
2526         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
2527                 .setPoolName(NatConstants.SNAT_IDPOOL_NAME)
2528                 .setLow(NatConstants.SNAT_ID_LOW_VALUE)
2529                 .setHigh(NatConstants.SNAT_ID_HIGH_VALUE)
2530                 .build();
2531         try {
2532             Future<RpcResult<CreateIdPoolOutput>> result = idManager.createIdPool(createPool);
2533             if (result != null && result.get().isSuccessful()) {
2534                 LOG.debug("createGroupIdPool : GroupIdPool created successfully");
2535             } else {
2536                 LOG.error("createGroupIdPool : Unable to create GroupIdPool");
2537             }
2538         } catch (InterruptedException | ExecutionException e) {
2539             LOG.error("createGroupIdPool : Failed to create PortPool for NAPT Service", e);
2540         }
2541     }
2542
2543     public static boolean getSwitchStatus(DataBroker broker, BigInteger switchId) {
2544         NodeId nodeId = new NodeId("openflow:" + switchId);
2545         LOG.debug("getSwitchStatus : Querying switch with dpnId {} is up/down", nodeId);
2546         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeInstanceId
2547             = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight
2548                     .inventory.rev130819.nodes.Node.class, new NodeKey(nodeId)).build();
2549         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeOptional =
2550                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
2551                         LogicalDatastoreType.OPERATIONAL, nodeInstanceId);
2552         if (nodeOptional.isPresent()) {
2553             LOG.debug("getSwitchStatus : Switch {} is up", nodeId);
2554             return true;
2555         }
2556         LOG.debug("getSwitchStatus : Switch {} is down", nodeId);
2557         return false;
2558     }
2559
2560     public static boolean isExternalNetwork(DataBroker broker, Uuid networkId) {
2561         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
2562         Optional<Networks> networkData =
2563                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
2564                         broker, LogicalDatastoreType.CONFIGURATION, id);
2565         return networkData.isPresent();
2566     }
2567
2568     @Nullable
2569     public static String getElanInstancePhysicalNetwok(String elanInstanceName, DataBroker broker) {
2570         ElanInstance elanInstance =  getElanInstanceByName(elanInstanceName, broker);
2571         if (null != elanInstance) {
2572             return elanInstance.getPhysicalNetworkName();
2573         }
2574         return null;
2575
2576     }
2577
2578     public static Map<String, String> getOpenvswitchOtherConfigMap(BigInteger dpnId, DataBroker dataBroker) {
2579         String otherConfigVal = getProviderMappings(dpnId, dataBroker);
2580         return getMultiValueMap(otherConfigVal);
2581     }
2582
2583     public static Map<String, String> getMultiValueMap(String multiKeyValueStr) {
2584         if (Strings.isNullOrEmpty(multiKeyValueStr)) {
2585             return Collections.emptyMap();
2586         }
2587
2588         Map<String, String> valueMap = new HashMap<>();
2589         Splitter splitter = Splitter.on(OTHER_CONFIG_PARAMETERS_DELIMITER);
2590         for (String keyValue : splitter.split(multiKeyValueStr)) {
2591             String[] split = keyValue.split(OTHER_CONFIG_KEY_VALUE_DELIMITER, 2);
2592             if (split.length == 2) {
2593                 valueMap.put(split[0], split[1]);
2594             }
2595         }
2596
2597         return valueMap;
2598     }
2599
2600     public static Optional<Node> getBridgeRefInfo(BigInteger dpnId, DataBroker dataBroker) {
2601         InstanceIdentifier<BridgeRefEntry> bridgeRefInfoPath = InstanceIdentifier.create(BridgeRefInfo.class)
2602                 .child(BridgeRefEntry.class, new BridgeRefEntryKey(dpnId));
2603
2604         Optional<BridgeRefEntry> bridgeRefEntry =
2605                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
2606                         LogicalDatastoreType.OPERATIONAL, bridgeRefInfoPath);
2607         if (!bridgeRefEntry.isPresent()) {
2608             LOG.info("getBridgeRefInfo : bridgeRefEntry is not present for {}", dpnId);
2609             return Optional.absent();
2610         }
2611
2612         InstanceIdentifier<Node> nodeId =
2613                 bridgeRefEntry.get().getBridgeReference().getValue().firstIdentifierOf(Node.class);
2614
2615         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
2616                 LogicalDatastoreType.OPERATIONAL, nodeId);
2617     }
2618
2619     @Nullable
2620     public static String getProviderMappings(BigInteger dpId, DataBroker dataBroker) {
2621         return getBridgeRefInfo(dpId, dataBroker).toJavaUtil().map(node -> getOpenvswitchOtherConfigs(node,
2622                 PROVIDER_MAPPINGS, dataBroker)).orElse(null);
2623     }
2624
2625     @Nullable
2626     public static String getOpenvswitchOtherConfigs(Node node, String key, DataBroker dataBroker) {
2627         OvsdbNodeAugmentation ovsdbNode = node.augmentation(OvsdbNodeAugmentation.class);
2628         if (ovsdbNode == null) {
2629             Optional<Node> nodeFromReadOvsdbNode = readOvsdbNode(node, dataBroker);
2630             if (nodeFromReadOvsdbNode.isPresent()) {
2631                 ovsdbNode = nodeFromReadOvsdbNode.get().augmentation(OvsdbNodeAugmentation.class);
2632             }
2633         }
2634
2635         if (ovsdbNode != null && ovsdbNode.getOpenvswitchOtherConfigs() != null) {
2636             for (OpenvswitchOtherConfigs openvswitchOtherConfigs : ovsdbNode.getOpenvswitchOtherConfigs()) {
2637                 if (Objects.equals(openvswitchOtherConfigs.getOtherConfigKey(), key)) {
2638                     return openvswitchOtherConfigs.getOtherConfigValue();
2639                 }
2640             }
2641         }
2642         LOG.info("getOpenvswitchOtherConfigs : OtherConfigs is not present for ovsdbNode {}", node.getNodeId());
2643         return null;
2644     }
2645
2646     @NonNull
2647     public static Optional<Node> readOvsdbNode(Node bridgeNode, DataBroker dataBroker) {
2648         OvsdbBridgeAugmentation bridgeAugmentation = extractBridgeAugmentation(bridgeNode);
2649         if (bridgeAugmentation != null) {
2650             InstanceIdentifier<Node> ovsdbNodeIid =
2651                     (InstanceIdentifier<Node>) bridgeAugmentation.getManagedBy().getValue();
2652             return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
2653                     LogicalDatastoreType.OPERATIONAL, ovsdbNodeIid);
2654         }
2655         return Optional.absent();
2656
2657     }
2658
2659     @Nullable
2660     public static OvsdbBridgeAugmentation extractBridgeAugmentation(Node node) {
2661         if (node == null) {
2662             return null;
2663         }
2664         return node.augmentation(OvsdbBridgeAugmentation.class);
2665     }
2666
2667     public static String getDefaultFibRouteToSNATForSubnetJobKey(String subnetName, BigInteger dpnId) {
2668         return NatConstants.NAT_DJC_PREFIX + subnetName + dpnId;
2669     }
2670
2671     public static ExternalSubnets getExternalSubnets(DataBroker dataBroker) {
2672         InstanceIdentifier<ExternalSubnets> subnetsIdentifier =
2673                 InstanceIdentifier.builder(ExternalSubnets.class)
2674                 .build();
2675         try {
2676             Optional<ExternalSubnets> optionalExternalSubnets  = SingleTransactionDataBroker
2677                     .syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetsIdentifier);
2678             if (optionalExternalSubnets.isPresent()) {
2679                 return optionalExternalSubnets.get();
2680             }
2681         } catch (ReadFailedException e) {
2682             LOG.error("Failed to read the subnets from the datastore.");
2683         }
2684         return null;
2685
2686     }
2687
2688     public static void addFlow(TypedWriteTransaction<Configuration> confTx, IMdsalApiManager mdsalManager,
2689             BigInteger dpId, short tableId, String flowId, int priority, String flowName, BigInteger cookie,
2690             List<? extends MatchInfoBase> matches, List<InstructionInfo> instructions) {
2691         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority, flowName,
2692                 NatConstants.DEFAULT_IDLE_TIMEOUT, NatConstants.DEFAULT_IDLE_TIMEOUT, cookie, matches,
2693                 instructions);
2694         LOG.trace("syncFlow : Installing DpnId {}, flowId {}", dpId, flowId);
2695         mdsalManager.addFlow(confTx, flowEntity);
2696     }
2697
2698     public static void removeFlow(TypedReadWriteTransaction<Configuration> confTx, IMdsalApiManager mdsalManager,
2699             BigInteger dpId, short tableId, String flowId) throws ExecutionException, InterruptedException {
2700         LOG.trace("syncFlow : Removing Acl Flow DpnId {}, flowId {}", dpId, flowId);
2701         mdsalManager.removeFlow(confTx, dpId, flowId, tableId);
2702     }
2703
2704     public static String getIpv6FlowRef(BigInteger dpnId, short tableId, long routerID) {
2705         return new StringBuilder().append(NatConstants.IPV6_FLOWID_PREFIX).append(dpnId).append(NatConstants
2706                 .FLOWID_SEPARATOR).append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
2707     }
2708
2709     public static String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId,
2710                                                 ItmRpcService itmManager) {
2711         Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
2712         RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
2713         try {
2714             Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager
2715                     .getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder().setSourceDpid(srcDpId)
2716                             .setDestinationDpid(dstDpId).setTunnelType(tunType).build());
2717             rpcResult = result.get();
2718             if (!rpcResult.isSuccessful()) {
2719                 tunType = TunnelTypeGre.class ;
2720                 result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
2721                         .setSourceDpid(srcDpId)
2722                         .setDestinationDpid(dstDpId)
2723                         .setTunnelType(tunType)
2724                         .build());
2725                 rpcResult = result.get();
2726                 if (!rpcResult.isSuccessful()) {
2727                     LOG.warn("getTunnelInterfaceName : RPC Call to getTunnelInterfaceId returned with Errors {}",
2728                             rpcResult.getErrors());
2729                 } else {
2730                     return rpcResult.getResult().getInterfaceName();
2731                 }
2732                 LOG.warn("getTunnelInterfaceName : RPC Call to getTunnelInterfaceId returned with Errors {}",
2733                         rpcResult.getErrors());
2734             } else {
2735                 return rpcResult.getResult().getInterfaceName();
2736             }
2737         } catch (InterruptedException | ExecutionException | NullPointerException e) {
2738             LOG.error("getTunnelInterfaceName : Exception when getting tunnel interface Id for tunnel "
2739                     + "between {} and {}", srcDpId, dstDpId);
2740         }
2741         return null;
2742     }
2743
2744     public static Boolean isRouterInterfacePort(DataBroker broker, String ifaceName) {
2745         Port neutronPort = getNeutronPort(broker, ifaceName);
2746         if (neutronPort == null) {
2747             return Boolean.TRUE;
2748         } else {
2749             return (NatConstants.NETWORK_ROUTER_INTERFACE.equalsIgnoreCase(neutronPort.getDeviceOwner()) ? Boolean.TRUE
2750                 : Boolean.FALSE);
2751         }
2752     }
2753
2754     private static Port getNeutronPort(DataBroker broker, String ifaceName) {
2755         InstanceIdentifier<Port>
2756             portsIdentifier = InstanceIdentifier.create(Neutron.class)
2757             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports.class)
2758             .child(Port.class, new PortKey(new Uuid(ifaceName)));
2759         Optional<Port> portsOptional;
2760         try {
2761             portsOptional = SingleTransactionDataBroker
2762                 .syncReadOptional(broker, LogicalDatastoreType.CONFIGURATION, portsIdentifier);
2763         } catch (ReadFailedException e) {
2764             LOG.error("Read Failed Exception While Reading Neutron Port for {}", ifaceName, e);
2765             portsOptional = Optional.absent();
2766         }
2767         if (!portsOptional.isPresent()) {
2768             LOG.error("getNeutronPort : No neutron ports found for interface {}", ifaceName);
2769             return null;
2770         }
2771         return portsOptional.get();
2772     }
2773
2774     static ReentrantLock lockForNat(final BigInteger dataPath) {
2775         // FIXME: wrap this in an Identifier
2776         return JvmGlobalLocks.getLockForString(NatConstants.NAT_DJC_PREFIX + dataPath);
2777     }
2778
2779     public static void removeSnatEntriesForPort(DataBroker dataBroker, NaptManager naptManager,
2780         IMdsalApiManager mdsalManager, NeutronvpnService neutronVpnService,
2781         String interfaceName, String routerName) {
2782         Long routerId = NatUtil.getVpnId(dataBroker, routerName);
2783         if (routerId == NatConstants.INVALID_ID) {
2784             LOG.error("removeSnatEntriesForPort: routerId not found for routername {}", routerName);
2785             return;
2786         }
2787         BigInteger naptSwitch = getPrimaryNaptfromRouterName(dataBroker, routerName);
2788         if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
2789             LOG.error("removeSnatEntriesForPort: NaptSwitch is not elected for router {}"
2790                 + "with Id {}", routerName, routerId);
2791             return;
2792         }
2793         //getInternalIp for port
2794         List<String> fixedIps = getFixedIpsForPort(neutronVpnService, interfaceName);
2795         if (fixedIps == null) {
2796             LOG.error("removeSnatEntriesForPort: Internal Ips not found for InterfaceName {} in router {} with id {}",
2797                 interfaceName, routerName, routerId);
2798             return;
2799         }
2800         List<ProtocolTypes> protocolTypesList = getPortocolList();
2801         for (String internalIp : fixedIps) {
2802             LOG.debug("removeSnatEntriesForPort: Internal Ip retrieved for interface {} is {} in router with Id {}",
2803                 interfaceName, internalIp, routerId);
2804             for (ProtocolTypes protocol : protocolTypesList) {
2805                 List<Integer> portList = NatUtil.getInternalIpPortListInfo(dataBroker, routerId, internalIp, protocol);
2806                 if (portList != null) {
2807                     for (Integer portnum : portList) {
2808                         //build and remove the flow in outbound table
2809                         removeNatFlow(mdsalManager, naptSwitch, NwConstants.OUTBOUND_NAPT_TABLE,
2810                             routerId, internalIp, portnum, protocol.getName());
2811
2812                         //build and remove the flow in inboundtable
2813
2814                         removeNatFlow(mdsalManager, naptSwitch, NwConstants.INBOUND_NAPT_TABLE, routerId,
2815                             internalIp, portnum, protocol.getName());
2816
2817                         //Get the external IP address and the port from the model
2818
2819                         NAPTEntryEvent.Protocol proto = protocol.toString().equals(ProtocolTypes.TCP.toString())
2820                             ? NAPTEntryEvent.Protocol.TCP : NAPTEntryEvent.Protocol.UDP;
2821                         IpPortExternal ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId,
2822                             internalIp, String.valueOf(portnum), proto);
2823                         if (ipPortExternal == null) {
2824                             LOG.error("removeSnatEntriesForPort: Mapping for internalIp {} "
2825                                 + "with port {} is not found in "
2826                                 + "router with Id {}", internalIp, portnum, routerId);
2827                             return;
2828                         }
2829                         String externalIpAddress = ipPortExternal.getIpAddress();
2830                         String internalIpPort = internalIp + ":" + portnum;
2831                         // delete the entry from IntExtIpPortMap DS
2832
2833                         naptManager.removeFromIpPortMapDS(routerId, internalIpPort, proto);
2834                         naptManager.removePortFromPool(internalIpPort, externalIpAddress);
2835
2836                     }
2837                 } else {
2838                     LOG.debug("removeSnatEntriesForPort: No {} session for interface {} with internalIP {} "
2839                             + "in router with id {}",
2840                         protocol, interfaceName, internalIp, routerId);
2841                 }
2842             }
2843             // delete the entry from SnatIntIpPortMap DS
2844             LOG.debug("removeSnatEntriesForPort: Removing InternalIp :{} of router {} from snatint-ip-port-map",
2845                 internalIp, routerId);
2846             naptManager.removeFromSnatIpPortDS(routerId, internalIp);
2847         }
2848     }
2849
2850     private static List<String> getFixedIpsForPort(NeutronvpnService neutronVpnService, String interfname) {
2851         LOG.debug("getFixedIpsForPort: getFixedIpsForPort method is called for interface {}", interfname);
2852         try {
2853             Future<RpcResult<GetFixedIPsForNeutronPortOutput>> result =
2854                 neutronVpnService.getFixedIPsForNeutronPort(new GetFixedIPsForNeutronPortInputBuilder()
2855                     .setPortId(new Uuid(interfname)).build());
2856
2857             RpcResult<GetFixedIPsForNeutronPortOutput> rpcResult = result.get();
2858             if (!rpcResult.isSuccessful()) {
2859                 LOG.error("getFixedIpsForPort: RPC Call to GetFixedIPsForNeutronPortOutput returned with Errors {}",
2860                     rpcResult.getErrors());
2861             } else {
2862                 return rpcResult.getResult().getFixedIPs();
2863             }
2864         } catch (InterruptedException | ExecutionException | NullPointerException ex) {
2865             LOG.error("getFixedIpsForPort: Exception while receiving fixedIps for port {}", interfname, ex);
2866         }
2867         return null;
2868     }
2869
2870     private static List<ProtocolTypes> getPortocolList() {
2871         List<ProtocolTypes> protocollist = new ArrayList<>();
2872         protocollist.add(ProtocolTypes.TCP);
2873         protocollist.add(ProtocolTypes.UDP);
2874         return protocollist;
2875     }
2876
2877     private static void removeNatFlow(IMdsalApiManager mdsalManager, BigInteger dpnId, short tableId, Long routerId,
2878         String ipAddress, int ipPort, String protocol) {
2879
2880         String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(routerId), ipAddress, ipPort,
2881             protocol);
2882         FlowEntity snatFlowEntity = NatUtil.buildFlowEntity(dpnId, tableId, switchFlowRef);
2883
2884         mdsalManager.removeFlow(snatFlowEntity);
2885         LOG.debug("removeNatFlow: Removed the flow in table {} for the switch with the DPN ID {} for "
2886             + "router {} ip {} port {}", tableId, dpnId, routerId, ipAddress, ipPort);
2887     }
2888
2889     public static String getDpnFromNodeRef(NodeRef node) {
2890         PathArgument pathArgument = Iterables.get(node.getValue().getPathArguments(), 1);
2891         InstanceIdentifier.IdentifiableItem<?, ?> item = Arguments.checkInstanceOf(pathArgument,
2892             InstanceIdentifier.IdentifiableItem.class);
2893         NodeKey key = Arguments.checkInstanceOf(item.getKey(), NodeKey.class);
2894         String dpnKey = key.getId().getValue();
2895         String dpnID = null;
2896         if (dpnKey.contains(NatConstants.COLON_SEPARATOR)) {
2897             dpnID = new BigInteger(dpnKey.split(NatConstants.COLON_SEPARATOR)[1]).toString();
2898         }
2899         return dpnID;
2900     }
2901 }