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