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