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