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