3c4f16f1813a0a5945b390b095f3d4617f0d04b0
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / internal / NatUtil.java
1 /*
2  * Copyright © 2016, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.natservice.internal;
10
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
14 import java.math.BigInteger;
15 import java.net.InetAddress;
16 import java.net.UnknownHostException;
17 import java.util.ArrayList;
18 import java.util.Collection;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Objects;
25 import java.util.concurrent.ExecutionException;
26 import java.util.concurrent.Future;
27 import java.util.stream.Collectors;
28 import javax.annotation.Nonnull;
29 import javax.annotation.Nullable;
30 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
32 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
33 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
34 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
35 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
36 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
37 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
38 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
39 import org.opendaylight.genius.mdsalutil.ActionInfo;
40 import org.opendaylight.genius.mdsalutil.FlowEntity;
41 import org.opendaylight.genius.mdsalutil.FlowEntityBuilder;
42 import org.opendaylight.genius.mdsalutil.InstructionInfo;
43 import org.opendaylight.genius.mdsalutil.MDSALUtil;
44 import org.opendaylight.genius.mdsalutil.MatchInfo;
45 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
46 import org.opendaylight.genius.mdsalutil.NwConstants;
47 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
48 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
49 import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
50 import org.opendaylight.genius.mdsalutil.actions.ActionPushVlan;
51 import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
52 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldVlanVid;
53 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
54 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
55 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
56 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
57 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
58 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
59 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
60 import org.opendaylight.netvirt.elanmanager.api.IElanService;
61 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
62 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
63 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
64 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
65 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
66 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
69 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
70 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
71 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
73 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
74 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
75 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCase;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInputBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInputBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.DpnRouters;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.LearntVpnVipToPortData;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PrefixToInterface;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInterfaceOpData;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersList;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersListBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersListKey;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersList;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersListBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersListKey;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPortKey;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsKey;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
139 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;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalSubnets;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpPortInfo;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpMap;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterIdName;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterToVpnMapping;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.SnatintIpPortMap;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCountersKey;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.SubnetsKey;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPortsKey;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.PortsKey;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMapKey;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMapping;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingKey;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolTypeKey;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapKey;
178 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;
179 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
180 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
181 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIds;
182 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsBuilder;
183 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsKey;
184 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.to.vpn.mapping.Routermapping;
185 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.to.vpn.mapping.RoutermappingKey;
186 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMap;
187 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMapKey;
188 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
189 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPortKey;
190 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
191 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeKey;
192 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkMaps;
193 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
194 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
195 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
196 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
197 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey;
198 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
199 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
200 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
201 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
202 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
203 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
204 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
205 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.RouterKey;
206 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
207 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
208 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
209 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
210 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
211 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
212 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
213 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionResubmitRpcAddGroupCase;
214 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;
215 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
216 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
217 import org.opendaylight.yangtools.yang.common.RpcResult;
218 import org.slf4j.Logger;
219 import org.slf4j.LoggerFactory;
220
221 public final class NatUtil {
222
223     private static String OF_URI_SEPARATOR = ":";
224     private static final Logger LOG = LoggerFactory.getLogger(NatUtil.class);
225
226     private NatUtil() { }
227
228     /*
229      getCookieSnatFlow() computes and returns a unique cookie value for the NAT flows using the router ID as the
230       reference value.
231      */
232     public static BigInteger getCookieSnatFlow(long routerId) {
233         return NatConstants.COOKIE_NAPT_BASE.add(new BigInteger("0110000", 16)).add(
234             BigInteger.valueOf(routerId));
235     }
236
237     /*
238       getCookieNaptFlow() computes and returns a unique cookie value for the NAPT flows using the router ID as the
239        reference value.
240     */
241     public static BigInteger getCookieNaptFlow(long routerId) {
242         return NatConstants.COOKIE_NAPT_BASE.add(new BigInteger("0111000", 16)).add(
243             BigInteger.valueOf(routerId));
244     }
245
246     /*
247         getVpnId() returns the VPN ID from the VPN name
248      */
249     public static long getVpnId(DataBroker broker, String vpnName) {
250         if (vpnName == null) {
251             return NatConstants.INVALID_ID;
252         }
253
254         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
255             .instance.to.vpn.id.VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
256         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
257                 .instance.to.vpn.id.VpnInstance> vpnInstance =
258                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
259                         LogicalDatastoreType.CONFIGURATION, id);
260
261         long vpnId = NatConstants.INVALID_ID;
262         if (vpnInstance.isPresent()) {
263             Long vpnIdAsLong = vpnInstance.get().getVpnId();
264             if (vpnIdAsLong != null) {
265                 vpnId = vpnIdAsLong;
266             }
267         }
268         return vpnId;
269     }
270
271     public static Long getNetworkVpnIdFromRouterId(DataBroker broker, long routerId) {
272         //Get the external network ID from the ExternalRouter model
273         Uuid networkId = NatUtil.getNetworkIdFromRouterId(broker, routerId);
274         if (networkId == null) {
275             LOG.error("getNetworkVpnIdFromRouterId : networkId is null");
276             return NatConstants.INVALID_ID;
277         }
278
279         //Get the VPN ID from the ExternalNetworks model
280         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(broker, networkId);
281         if (vpnUuid == null) {
282             LOG.error("getNetworkVpnIdFromRouterId : vpnUuid is null");
283             return NatConstants.INVALID_ID;
284         }
285         Long vpnId = NatUtil.getVpnId(broker, vpnUuid.getValue());
286         return vpnId;
287     }
288
289     static InstanceIdentifier<RouterPorts> getRouterPortsId(String routerId) {
290         return InstanceIdentifier.builder(FloatingIpInfo.class)
291             .child(RouterPorts.class, new RouterPortsKey(routerId)).build();
292     }
293
294     static InstanceIdentifier<Routermapping> getRouterVpnMappingId(String routerId) {
295         return InstanceIdentifier.builder(RouterToVpnMapping.class)
296             .child(Routermapping.class, new RoutermappingKey(routerId)).build();
297     }
298
299     static InstanceIdentifier<Ports> getPortsIdentifier(String routerId, String portName) {
300         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId))
301             .child(Ports.class, new PortsKey(portName)).build();
302     }
303
304     static InstanceIdentifier<InternalToExternalPortMap> getIntExtPortMapIdentifier(String routerId, String portName,
305                                                                                     String internalIp) {
306         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId))
307             .child(Ports.class, new PortsKey(portName))
308             .child(InternalToExternalPortMap.class, new InternalToExternalPortMapKey(internalIp)).build();
309     }
310
311     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
312         .instance.to.vpn.id.VpnInstance> getVpnInstanceToVpnIdIdentifier(String vpnName) {
313         return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
314             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
315                     .instance.to.vpn.id.VpnInstance.class,
316                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
317                     .instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
318     }
319
320     static String getVpnInstanceFromVpnIdentifier(DataBroker broker, long vpnId) {
321         InstanceIdentifier<VpnIds> id = InstanceIdentifier.builder(VpnIdToVpnInstance.class)
322             .child(VpnIds.class, new VpnIdsKey(vpnId)).build();
323         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
324                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(VpnIds::getVpnInstanceName).orElse(null);
325     }
326
327     /*
328        getFlowRef() returns a string identfier for the SNAT flows using the router ID as the reference.
329     */
330     public static String getFlowRef(BigInteger dpnId, short tableId, long routerID, String ip) {
331         return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
332                 .FLOWID_SEPARATOR + routerID + NatConstants.FLOWID_SEPARATOR + ip;
333     }
334
335     public static String getFlowRef(BigInteger dpnId, short tableId, InetAddress destPrefix, long vpnId) {
336         return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
337                 .FLOWID_SEPARATOR + destPrefix.getHostAddress() + NatConstants.FLOWID_SEPARATOR + vpnId;
338     }
339
340     public static String getNaptFlowRef(BigInteger dpnId, short tableId, String routerID, String ip, int port) {
341         return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NatConstants.FLOWID_SEPARATOR + tableId + NatConstants
342                 .FLOWID_SEPARATOR + routerID + NatConstants.FLOWID_SEPARATOR + ip + NatConstants.FLOWID_SEPARATOR
343                 + port;
344     }
345
346     static Uuid getNetworkIdFromRouterId(DataBroker broker, long routerId) {
347         String routerName = getRouterName(broker, routerId);
348         if (routerName == null) {
349             LOG.error("getNetworkIdFromRouterId - empty routerName received");
350             return null;
351         }
352         return getNetworkIdFromRouterName(broker, routerName);
353     }
354
355     static Uuid getNetworkIdFromRouterName(DataBroker broker, String routerName) {
356         if (routerName == null) {
357             LOG.error("getNetworkIdFromRouterName - empty routerName received");
358             return null;
359         }
360         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerName);
361         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
362                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(Routers::getNetworkId).orElse(null);
363     }
364
365     static InstanceIdentifier<Routers> buildRouterIdentifier(String routerId) {
366         InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class)
367             .child(Routers.class, new RoutersKey(routerId)).build();
368         return routerInstanceIndentifier;
369     }
370
371     private static InstanceIdentifier<RouterIds> buildRouterIdentifier(Long routerId) {
372         InstanceIdentifier<RouterIds> routerIds = InstanceIdentifier.builder(RouterIdName.class)
373             .child(RouterIds.class, new RouterIdsKey(routerId)).build();
374         return routerIds;
375     }
376
377     /**
378      * Return if SNAT is enabled for the given router.
379      *
380      * @param broker   The DataBroker
381      * @param routerId The router
382      * @return boolean true if enabled, otherwise false
383      */
384     static boolean isSnatEnabledForRouterId(DataBroker broker, String routerId) {
385         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerId);
386         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
387                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(Routers::isEnableSnat).orElse(false);
388     }
389
390     public static Uuid getVpnIdfromNetworkId(DataBroker broker, Uuid networkId) {
391         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
392         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
393                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(Networks::getVpnid).orElse(null);
394     }
395
396     public static ProviderTypes getProviderTypefromNetworkId(DataBroker broker, Uuid networkId) {
397         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
398         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
399                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(Networks::getProviderNetworkType).orElse(null);
400     }
401
402     @Nonnull
403     public static List<Uuid> getRouterIdsfromNetworkId(DataBroker broker, Uuid networkId) {
404         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
405         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
406                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(Networks::getRouterIds).orElse(
407                 Collections.emptyList());
408     }
409
410     static String getAssociatedExternalNetwork(DataBroker dataBroker, String routerId) {
411         InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
412         Optional<Routers> routerData =
413                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
414                         LogicalDatastoreType.CONFIGURATION, id);
415         if (routerData.isPresent()) {
416             Uuid networkId = routerData.get().getNetworkId();
417             if (networkId != null) {
418                 return networkId.getValue();
419             }
420         }
421         LOG.info("getAssociatedExternalNetwork : External Network missing for routerid : {}", routerId);
422         return null;
423     }
424
425     private static InstanceIdentifier<Networks> buildNetworkIdentifier(Uuid networkId) {
426         return InstanceIdentifier.builder(ExternalNetworks.class)
427             .child(Networks.class, new NetworksKey(networkId)).build();
428     }
429
430     public static BigInteger getPrimaryNaptfromRouterId(DataBroker broker, Long routerId) {
431         // convert routerId to Name
432         String routerName = getRouterName(broker, routerId);
433         if (routerName == null) {
434             LOG.error("getPrimaryNaptfromRouterId - empty routerName received");
435             return null;
436         }
437         return getPrimaryNaptfromRouterName(broker, routerName);
438     }
439
440     public static BigInteger getPrimaryNaptfromRouterName(DataBroker broker, String routerName) {
441         if (routerName == null) {
442             LOG.error("getPrimaryNaptfromRouterName - empty routerName received");
443             return null;
444         }
445         InstanceIdentifier<RouterToNaptSwitch> id = buildNaptSwitchIdentifier(routerName);
446         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
447                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(RouterToNaptSwitch::getPrimarySwitchId).orElse(
448                 null);
449     }
450
451     public static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchIdentifier(String routerId) {
452         InstanceIdentifier<RouterToNaptSwitch> rtrNaptSw = InstanceIdentifier.builder(NaptSwitches.class)
453             .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerId)).build();
454         return rtrNaptSw;
455     }
456
457     public static String getRouterName(DataBroker broker, Long routerId) {
458         InstanceIdentifier<RouterIds> id = buildRouterIdentifier(routerId);
459         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
460                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(RouterIds::getRouterName).orElse(null);
461     }
462
463     static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String vrfId) {
464         return InstanceIdentifier.builder(VpnInstanceOpData.class)
465             .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vrfId)).build();
466     }
467
468     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, BigInteger cookie, String flowId) {
469         return new FlowEntityBuilder()
470                 .setDpnId(dpnId)
471                 .setTableId(tableId)
472                 .setCookie(cookie)
473                 .setFlowId(flowId)
474                 .build();
475     }
476
477     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId) {
478         return new FlowEntityBuilder()
479                 .setDpnId(dpnId)
480                 .setTableId(tableId)
481                 .setFlowId(flowId)
482                 .build();
483     }
484
485     public static long getIpAddress(byte[] rawIpAddress) {
486         return ((rawIpAddress[0] & 0xFF) << 3 * 8) + ((rawIpAddress[1] & 0xFF) << 2 * 8)
487             + ((rawIpAddress[2] & 0xFF) << 1 * 8) + (rawIpAddress[3] & 0xFF) & 0xffffffffL;
488     }
489
490     public static String getEndpointIpAddressForDPN(DataBroker broker, BigInteger dpnId) {
491         String nextHopIp = null;
492         InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
493             InstanceIdentifier.builder(DpnEndpoints.class)
494                 .child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpnId)).build();
495         Optional<DPNTEPsInfo> tunnelInfo =
496                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
497                         LogicalDatastoreType.CONFIGURATION, tunnelInfoId);
498         if (tunnelInfo.isPresent()) {
499             List<TunnelEndPoints> nexthopIpList = tunnelInfo.get().getTunnelEndPoints();
500             if (nexthopIpList != null && !nexthopIpList.isEmpty()) {
501                 nextHopIp = nexthopIpList.get(0).getIpAddress().getIpv4Address().getValue();
502             }
503         }
504         return nextHopIp;
505     }
506
507     public static String getVpnRd(DataBroker broker, String vpnName) {
508
509         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
510             .instance.to.vpn.id.VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
511         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
512                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
513                 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
514                         .VpnInstance::getVrfId).orElse(null);
515     }
516
517     public static IpPortExternal getExternalIpPortMap(DataBroker broker, Long routerId, String internalIpAddress,
518                                                       String internalPort, NAPTEntryEvent.Protocol protocol) {
519         ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
520         InstanceIdentifier<IpPortMap> ipPortMapId =
521             buildIpToPortMapIdentifier(routerId, internalIpAddress, internalPort, protocolType);
522         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
523                 LogicalDatastoreType.CONFIGURATION, ipPortMapId).toJavaUtil().map(IpPortMap::getIpPortExternal).orElse(
524                 null);
525     }
526
527     private static InstanceIdentifier<IpPortMap> buildIpToPortMapIdentifier(Long routerId, String internalIpAddress,
528                                                                             String internalPort,
529                                                                             ProtocolTypes protocolType) {
530         return InstanceIdentifier.builder(IntextIpPortMap.class)
531             .child(IpPortMapping.class, new IpPortMappingKey(routerId))
532             .child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
533             .child(IpPortMap.class, new IpPortMapKey(internalIpAddress + ":" + internalPort)).build();
534     }
535
536     static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
537         return InstanceIdentifier.builder(VpnInterfaces.class)
538             .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build();
539     }
540
541     static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
542         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
543         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
544                 LogicalDatastoreType.CONFIGURATION, interfaceId).orNull();
545     }
546
547     public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
548         /*
549          * NodeConnectorId is of form 'openflow:dpnid:portnum'
550          */
551         String[] split = portId.getValue().split(OF_URI_SEPARATOR);
552         if (split.length != 3) {
553             LOG.error("getDpnFromNodeConnectorId : invalid portid : {}", portId.getValue());
554             return null;
555         }
556         return split[1];
557     }
558
559     public static BigInteger getDpIdFromInterface(
560         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
561             .state.Interface ifState) {
562         String lowerLayerIf = ifState.getLowerLayerIf().get(0);
563         NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
564         return new BigInteger(getDpnFromNodeConnectorId(nodeConnectorId));
565     }
566
567     public static String getRouterIdfromVpnInstance(DataBroker broker, String vpnName) {
568         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
569             .child(VpnMap.class, new VpnMapKey(new Uuid(vpnName))).build();
570         Optional<VpnMap> optionalVpnMap =
571                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
572                         LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
573         if (optionalVpnMap.isPresent()) {
574             Uuid routerId = optionalVpnMap.get().getRouterId();
575             if (routerId != null) {
576                 return routerId.getValue();
577             }
578         }
579         LOG.info("getRouterIdfromVpnInstance : Router not found for vpn : {}", vpnName);
580         return null;
581     }
582
583     static Uuid getVpnForRouter(DataBroker broker, String routerId) {
584         InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
585         Optional<VpnMaps> optionalVpnMaps =
586                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
587                         LogicalDatastoreType.CONFIGURATION, vpnMapsIdentifier);
588         if (optionalVpnMaps.isPresent() && optionalVpnMaps.get().getVpnMap() != null) {
589             List<VpnMap> allMaps = optionalVpnMaps.get().getVpnMap();
590             if (routerId != null) {
591                 for (VpnMap vpnMap : allMaps) {
592                     if (vpnMap.getRouterId() != null
593                         && routerId.equals(vpnMap.getRouterId().getValue())
594                         && !routerId.equals(vpnMap.getVpnId().getValue())) {
595                         return vpnMap.getVpnId();
596                     }
597                 }
598             }
599         }
600         LOG.debug("getVpnForRouter : VPN not found for routerID:{}", routerId);
601         return null;
602     }
603
604     static long getAssociatedVpn(DataBroker broker, String routerName) {
605         InstanceIdentifier<Routermapping> routerMappingId = NatUtil.getRouterVpnMappingId(routerName);
606         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
607                 LogicalDatastoreType.OPERATIONAL, routerMappingId).toJavaUtil().map(Routermapping::getVpnId).orElse(
608                 NatConstants.INVALID_ID);
609     }
610
611     public static String getAssociatedVPN(DataBroker dataBroker, Uuid networkId) {
612         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
613         if (vpnUuid == null) {
614             LOG.error("getAssociatedVPN : No VPN instance associated with ext network {}", networkId);
615             return null;
616         }
617         return vpnUuid.getValue();
618     }
619
620     // TODO Clean up the exception handling
621     @SuppressWarnings("checkstyle:IllegalCatch")
622     public static void addPrefixToBGP(DataBroker broker,
623                                       IBgpManager bgpManager,
624                                       IFibManager fibManager,
625                                       String vpnName,
626                                       String rd,
627                                       Uuid subnetId,
628                                       String prefix,
629                                       String nextHopIp,
630                                       String parentVpnRd,
631                                       String macAddress,
632                                       long label,
633                                       long l3vni,
634                                       RouteOrigin origin,
635                                       BigInteger dpId) {
636         try {
637             LOG.info("addPrefixToBGP : Adding Fib entry rd {} prefix {} nextHop {} label {}", rd,
638                     prefix, nextHopIp, label);
639             if (nextHopIp == null) {
640                 LOG.error("addPrefixToBGP : prefix {} rd {} failed since nextHopIp cannot be null.",
641                         prefix, rd);
642                 return;
643             }
644
645             addPrefixToInterface(broker, getVpnId(broker, vpnName), null /*interfaceName*/,prefix, dpId,
646                     subnetId, Prefixes.PrefixCue.Nat);
647             fibManager.addOrUpdateFibEntry(rd, macAddress, prefix,
648                     Collections.singletonList(nextHopIp), VrfEntry.EncapType.Mplsgre, (int)label, l3vni /*l3vni*/,
649                     null /*gatewayMacAddress*/, parentVpnRd, origin, null /*writeTxn*/);
650             if (rd != null && !rd.equalsIgnoreCase(vpnName)) {
651             /* Publish to Bgp only if its an INTERNET VPN */
652                 bgpManager.advertisePrefix(rd, null /*macAddress*/, prefix, Collections.singletonList(nextHopIp),
653                         VrfEntry.EncapType.Mplsgre, (int) label, 0 /*l3vni*/, 0 /*l2vni*/,
654                         null /*gatewayMac*/);
655             }
656             LOG.info("addPrefixToBGP : Added Fib entry rd {} prefix {} nextHop {} label {}", rd,
657                     prefix, nextHopIp, label);
658         } catch (Exception e) {
659             LOG.error("addPrefixToBGP : Add prefix rd {} prefix {} nextHop {} label {} failed", rd,
660                     prefix, nextHopIp, label, e);
661         }
662     }
663
664     static void addPrefixToInterface(DataBroker broker, long vpnId, String interfaceName, String ipPrefix,
665                                      BigInteger dpId, Uuid subnetId, Prefixes.PrefixCue prefixCue) {
666         InstanceIdentifier<Prefixes> prefixId = InstanceIdentifier.builder(PrefixToInterface.class)
667                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
668                         .VpnIds.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix
669                         .to._interface.VpnIdsKey(vpnId))
670                 .child(Prefixes.class, new PrefixesKey(ipPrefix)).build();
671         PrefixesBuilder prefixBuilder = new PrefixesBuilder().setDpnId(dpId).setIpAddress(ipPrefix);
672         prefixBuilder.setVpnInterfaceName(interfaceName).setSubnetId(subnetId).setPrefixCue(prefixCue);
673         try {
674             SingleTransactionDataBroker.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, prefixId,
675                     prefixBuilder.build());
676         } catch (TransactionCommitFailedException e) {
677             LOG.error("addPrefixToInterface : Failed to write prefxi-to-interface for {} vpn-id {} DPN {}",
678                     ipPrefix, vpnId, dpId, e);
679         }
680     }
681
682     public static void deletePrefixToInterface(DataBroker broker, long vpnId, String ipPrefix) {
683         try {
684             SingleTransactionDataBroker.syncDelete(broker, LogicalDatastoreType.OPERATIONAL,
685                     InstanceIdentifier.builder(PrefixToInterface.class)
686                     .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
687                             .VpnIds.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
688                             .prefix.to._interface.VpnIdsKey(vpnId)).child(Prefixes.class, new PrefixesKey(ipPrefix))
689                     .build());
690         } catch (TransactionCommitFailedException e) {
691             LOG.error("addPrefixToInterface : Failed to write prefxi-to-interface for vpn-id {}",
692                     vpnId, e);
693         }
694     }
695
696     static InstanceIdentifier<Ports> buildPortToIpMapIdentifier(String routerId, String portName) {
697         InstanceIdentifier<Ports> ipPortMapId = InstanceIdentifier.builder(FloatingIpInfo.class)
698             .child(RouterPorts.class, new RouterPortsKey(routerId)).child(Ports.class, new PortsKey(portName)).build();
699         return ipPortMapId;
700     }
701
702     static InstanceIdentifier<RouterPorts> buildRouterPortsIdentifier(String routerId) {
703         InstanceIdentifier<RouterPorts> routerInstanceIndentifier = InstanceIdentifier.builder(FloatingIpInfo.class)
704             .child(RouterPorts.class, new RouterPortsKey(routerId)).build();
705         return routerInstanceIndentifier;
706     }
707
708     @Nonnull
709     public static List<Integer> getInternalIpPortListInfo(DataBroker dataBroker, Long routerId,
710                                                           String internalIpAddress, ProtocolTypes protocolType) {
711         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
712                 LogicalDatastoreType.CONFIGURATION,
713                 buildSnatIntIpPortIdentifier(routerId, internalIpAddress, protocolType)).toJavaUtil().map(
714                 IntIpProtoType::getPorts).orElse(Collections.emptyList());
715     }
716
717     public static InstanceIdentifier<IntIpProtoType> buildSnatIntIpPortIdentifier(Long routerId,
718                                                                                   String internalIpAddress,
719                                                                                   ProtocolTypes protocolType) {
720         InstanceIdentifier<IntIpProtoType> intIpProtocolTypeId =
721             InstanceIdentifier.builder(SnatintIpPortMap.class)
722                 .child(IntipPortMap.class, new IntipPortMapKey(routerId))
723                 .child(IpPort.class, new IpPortKey(internalIpAddress))
724                 .child(IntIpProtoType.class, new IntIpProtoTypeKey(protocolType)).build();
725         return intIpProtocolTypeId;
726     }
727
728     public static InstanceIdentifier<IpPort> buildSnatIntIpPortIdentifier(Long routerId,
729             String internalIpAddress) {
730         InstanceIdentifier<IpPort> intIpProtocolTypeId =
731             InstanceIdentifier.builder(SnatintIpPortMap.class)
732                 .child(IntipPortMap.class, new IntipPortMapKey(routerId))
733                 .child(IpPort.class, new IpPortKey(internalIpAddress)).build();
734         return intIpProtocolTypeId;
735     }
736
737     @Nullable
738     public static IpPort getInternalIpPortInfo(DataBroker dataBroker, Long routerId,
739                                                           String internalIpAddress) {
740         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
741                 LogicalDatastoreType.CONFIGURATION,
742                 buildSnatIntIpPortIdentifier(routerId, internalIpAddress)).orNull();
743     }
744
745     public static ProtocolTypes getProtocolType(NAPTEntryEvent.Protocol protocol) {
746         ProtocolTypes protocolType = ProtocolTypes.TCP.toString().equals(protocol.toString())
747             ? ProtocolTypes.TCP : ProtocolTypes.UDP;
748         return protocolType;
749     }
750
751     public static InstanceIdentifier<NaptSwitches> getNaptSwitchesIdentifier() {
752         return InstanceIdentifier.create(NaptSwitches.class);
753     }
754
755     public static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchRouterIdentifier(String routerId) {
756         return InstanceIdentifier.create(NaptSwitches.class)
757             .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerId));
758     }
759
760     public static String getGroupIdKey(String routerName) {
761         return "snatmiss." + routerName;
762     }
763
764     public static long createGroupId(String groupIdKey, IdManagerService idManager) {
765         AllocateIdInput getIdInput = new AllocateIdInputBuilder()
766             .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
767             .build();
768         try {
769             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
770             RpcResult<AllocateIdOutput> rpcResult = result.get();
771             return rpcResult.getResult().getIdValue();
772         } catch (NullPointerException | InterruptedException | ExecutionException e) {
773             LOG.error("createGroupId : Creating Group with Key: {} failed", groupIdKey, e);
774         }
775         return 0;
776     }
777
778     // TODO Clean up the exception handling
779     @SuppressWarnings("checkstyle:IllegalCatch")
780     public static void removePrefixFromBGP(IBgpManager bgpManager, IFibManager fibManager,
781                                            String rd, String prefix, String vpnName, Logger log) {
782         try {
783             LOG.debug("removePrefixFromBGP: Removing Fib entry rd {} prefix {}", rd, prefix);
784             fibManager.removeFibEntry(rd, prefix, null);
785             if (rd != null && !rd.equalsIgnoreCase(vpnName)) {
786                 bgpManager.withdrawPrefix(rd, prefix);
787             }
788             LOG.info("removePrefixFromBGP: Removed Fib entry rd {} prefix {}", rd, prefix);
789         } catch (Exception e) {
790             log.error("removePrefixFromBGP : Delete prefix for rd {} prefix {} vpnName {} failed",
791                     rd, prefix, vpnName, e);
792         }
793     }
794
795     public static IpPortMapping getIportMapping(DataBroker broker, long routerId) {
796         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
797                 LogicalDatastoreType.CONFIGURATION, getIportMappingIdentifier(routerId)).orNull();
798     }
799
800     public static InstanceIdentifier<IpPortMapping> getIportMappingIdentifier(long routerId) {
801         return InstanceIdentifier.builder(IntextIpPortMap.class)
802             .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
803     }
804
805     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
806         .natservice.rev160111.intext.ip.map.IpMapping> getIpMappingBuilder(Long routerId) {
807         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111
808             .intext.ip.map.IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
809             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map
810                 .IpMapping.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111
811                 .intext.ip.map.IpMappingKey(routerId)).build();
812         return idBuilder;
813     }
814
815     @Nonnull
816     public static Collection<String> getExternalIpsForRouter(DataBroker dataBroker, Long routerId) {
817         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext
818             .ip.map.IpMapping> ipMappingOptional =
819                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
820                         LogicalDatastoreType.OPERATIONAL, getIpMappingBuilder(routerId));
821         // Ensure there are no duplicates
822         Collection<String> externalIps = new HashSet<>();
823         if (ipMappingOptional.isPresent()) {
824             List<IpMap> ipMaps = ipMappingOptional.get().getIpMap();
825             for (IpMap ipMap : ipMaps) {
826                 externalIps.add(ipMap.getExternalIp());
827             }
828         }
829         return externalIps;
830     }
831
832     @Nonnull
833     public static List<String> getExternalIpsForRouter(DataBroker dataBroker, String routerName) {
834         Routers routerData = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
835         if (routerData != null) {
836             return NatUtil.getIpsListFromExternalIps(routerData.getExternalIps());
837         }
838
839         return Collections.emptyList();
840     }
841
842     @Nonnull
843     public static Map<String, Long> getExternalIpsLabelForRouter(DataBroker dataBroker, Long routerId) {
844         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext
845             .ip.map.IpMapping> ipMappingOptional =
846                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
847                         LogicalDatastoreType.OPERATIONAL, getIpMappingBuilder(routerId));
848         Map<String, Long> externalIpsLabel = new HashMap<>();
849         if (ipMappingOptional.isPresent()) {
850             List<IpMap> ipMaps = ipMappingOptional.get().getIpMap();
851             for (IpMap ipMap : ipMaps) {
852                 externalIpsLabel.put(ipMap.getExternalIp(), ipMap.getLabel());
853             }
854         }
855         return externalIpsLabel;
856     }
857
858     public static String getLeastLoadedExternalIp(DataBroker dataBroker, long segmentId) {
859         String leastLoadedExternalIp = null;
860         InstanceIdentifier<ExternalCounters> id =
861             InstanceIdentifier.builder(ExternalIpsCounter.class)
862                 .child(ExternalCounters.class, new ExternalCountersKey(segmentId)).build();
863         Optional<ExternalCounters> externalCountersData =
864             MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
865         if (externalCountersData.isPresent()) {
866             ExternalCounters externalCounter = externalCountersData.get();
867             List<ExternalIpCounter> externalIpCounterList = externalCounter.getExternalIpCounter();
868             short countOfLstLoadExtIp = 32767;
869             for (ExternalIpCounter externalIpCounter : externalIpCounterList) {
870                 String curExternalIp = externalIpCounter.getExternalIp();
871                 short countOfCurExtIp = externalIpCounter.getCounter();
872                 if (countOfCurExtIp < countOfLstLoadExtIp) {
873                     countOfLstLoadExtIp = countOfCurExtIp;
874                     leastLoadedExternalIp = curExternalIp;
875                 }
876             }
877         }
878         return leastLoadedExternalIp;
879     }
880
881     @SuppressFBWarnings("PZLA_PREFER_ZERO_LENGTH_ARRAYS")
882     public static String[] getSubnetIpAndPrefix(DataBroker dataBroker, Uuid subnetId) {
883         String subnetIP = getSubnetIp(dataBroker, subnetId);
884         if (subnetIP != null) {
885             return getSubnetIpAndPrefix(subnetIP);
886         }
887         LOG.error("getSubnetIpAndPrefix : SubnetIP and Prefix missing for subnet : {}", subnetId);
888         return null;
889     }
890
891     public static String[] getSubnetIpAndPrefix(String subnetString) {
892         String[] subnetSplit = subnetString.split("/");
893         String subnetIp = subnetSplit[0];
894         String subnetPrefix = "0";
895         if (subnetSplit.length == 2) {
896             subnetPrefix = subnetSplit[1];
897         }
898         return new String[] {subnetIp, subnetPrefix};
899     }
900
901     public static String getSubnetIp(DataBroker dataBroker, Uuid subnetId) {
902         InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
903             .builder(Subnetmaps.class)
904             .child(Subnetmap.class, new SubnetmapKey(subnetId))
905             .build();
906         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
907                 LogicalDatastoreType.CONFIGURATION, subnetmapId).toJavaUtil().map(Subnetmap::getSubnetIp).orElse(null);
908
909     }
910
911     public static String[] getExternalIpAndPrefix(String leastLoadedExtIpAddr) {
912         String[] leastLoadedExtIpAddrSplit = leastLoadedExtIpAddr.split("/");
913         String leastLoadedExtIp = leastLoadedExtIpAddrSplit[0];
914         String leastLoadedExtIpPrefix = String.valueOf(NatConstants.DEFAULT_PREFIX);
915         if (leastLoadedExtIpAddrSplit.length == 2) {
916             leastLoadedExtIpPrefix = leastLoadedExtIpAddrSplit[1];
917         }
918         return new String[] {leastLoadedExtIp, leastLoadedExtIpPrefix};
919     }
920
921     @Nonnull
922     public static List<BigInteger> getDpnsForRouter(DataBroker dataBroker, String routerUuid) {
923         InstanceIdentifier id = InstanceIdentifier.builder(NeutronRouterDpns.class)
924             .child(RouterDpnList.class, new RouterDpnListKey(routerUuid)).build();
925         Optional<RouterDpnList> routerDpnListData =
926                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
927                         LogicalDatastoreType.OPERATIONAL, id);
928         List<BigInteger> dpns = new ArrayList<>();
929         if (routerDpnListData.isPresent()) {
930             List<DpnVpninterfacesList> dpnVpninterfacesList = routerDpnListData.get().getDpnVpninterfacesList();
931             for (DpnVpninterfacesList dpnVpnInterface : dpnVpninterfacesList) {
932                 dpns.add(dpnVpnInterface.getDpnId());
933             }
934         }
935         return dpns;
936     }
937
938     public static long getBgpVpnId(DataBroker dataBroker, String routerName) {
939         long bgpVpnId = NatConstants.INVALID_ID;
940         Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
941         if (bgpVpnUuid != null) {
942             bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
943         }
944         return bgpVpnId;
945     }
946
947     static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces
948         .RouterInterface getConfiguredRouterInterface(DataBroker broker, String interfaceName) {
949         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
950                 LogicalDatastoreType.CONFIGURATION, NatUtil.getRouterInterfaceId(interfaceName)).orNull();
951     }
952
953     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
954         .router.interfaces.RouterInterface> getRouterInterfaceId(String interfaceName) {
955         return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight
956             .netvirt.l3vpn.rev130911.RouterInterfaces.class)
957             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces
958                     .RouterInterface.class,
959                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces
960                     .RouterInterfaceKey(interfaceName)).build();
961     }
962
963     public static void addToNeutronRouterDpnsMap(DataBroker broker, String routerName, String interfaceName,
964             BigInteger dpId , WriteTransaction writeOperTxn) {
965
966         if (dpId.equals(BigInteger.ZERO)) {
967             LOG.warn("addToNeutronRouterDpnsMap : Could not retrieve dp id for interface {} "
968                     + "to handle router {} association model", interfaceName, routerName);
969             return;
970         }
971
972         LOG.debug("addToNeutronRouterDpnsMap : Adding the Router {} and DPN {} for the Interface {} in the "
973                 + "ODL-L3VPN : NeutronRouterDpn map", routerName, dpId, interfaceName);
974         InstanceIdentifier<DpnVpninterfacesList> dpnVpnInterfacesListIdentifier = getRouterDpnId(routerName, dpId);
975
976         Optional<DpnVpninterfacesList> optionalDpnVpninterfacesList =
977                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
978                         LogicalDatastoreType.OPERATIONAL, dpnVpnInterfacesListIdentifier);
979         org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns
980             .router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces routerInterface =
981             new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(interfaceName))
982             .setInterface(interfaceName).build();
983         if (optionalDpnVpninterfacesList.isPresent()) {
984             LOG.debug("addToNeutronRouterDpnsMap : RouterDpnList already present for the Router {} and DPN {} for the "
985                     + "Interface {} in the ODL-L3VPN : NeutronRouterDpn map", routerName, dpId, interfaceName);
986             writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, dpnVpnInterfacesListIdentifier
987                     .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
988                             .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
989                             new RouterInterfacesKey(interfaceName)), routerInterface, true);
990         } else {
991             LOG.debug("addToNeutronRouterDpnsMap : Building new RouterDpnList for the Router {} and DPN {} for the "
992                     + "Interface {} in the ODL-L3VPN : NeutronRouterDpn map", routerName, dpId, interfaceName);
993             RouterDpnListBuilder routerDpnListBuilder = new RouterDpnListBuilder();
994             routerDpnListBuilder.setRouterId(routerName);
995             DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
996             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
997                 .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces> routerInterfaces = new ArrayList<>();
998             routerInterfaces.add(routerInterface);
999             dpnVpnList.setRouterInterfaces(routerInterfaces);
1000             routerDpnListBuilder.setDpnVpninterfacesList(Collections.singletonList(dpnVpnList.build()));
1001             writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1002                     getRouterId(routerName),
1003                     routerDpnListBuilder.build(), true);
1004         }
1005     }
1006
1007     public static void addToDpnRoutersMap(DataBroker broker, String routerName, String interfaceName,
1008             BigInteger dpId, WriteTransaction writeOperTxn) {
1009         if (dpId.equals(BigInteger.ZERO)) {
1010             LOG.error("addToDpnRoutersMap : Could not retrieve dp id for interface {} to handle router {} "
1011                     + "association model", interfaceName, routerName);
1012             return;
1013         }
1014
1015         LOG.debug("addToDpnRoutersMap : Adding the DPN {} and router {} for the Interface {} in the ODL-L3VPN : "
1016                 + "DPNRouters map", dpId, routerName, interfaceName);
1017         InstanceIdentifier<DpnRoutersList> dpnRoutersListIdentifier = getDpnRoutersId(dpId);
1018
1019         Optional<DpnRoutersList> optionalDpnRoutersList =
1020                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1021                         LogicalDatastoreType.OPERATIONAL, dpnRoutersListIdentifier);
1022
1023         if (optionalDpnRoutersList.isPresent()) {
1024             RoutersList routersList = new RoutersListBuilder().setKey(new RoutersListKey(routerName))
1025                     .setRouter(routerName).build();
1026             List<RoutersList> routersListFromDs = optionalDpnRoutersList.get().getRoutersList();
1027             if (!routersListFromDs.contains(routersList)) {
1028                 LOG.debug("addToDpnRoutersMap : Router {} not present for the DPN {}"
1029                         + " in the ODL-L3VPN : DPNRouters map", routerName, dpId);
1030                 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1031                         dpnRoutersListIdentifier
1032                         .child(RoutersList.class, new RoutersListKey(routerName)), routersList, true);
1033             } else {
1034                 LOG.debug("addToDpnRoutersMap : Router {} already mapped to the DPN {} in the ODL-L3VPN : "
1035                         + "DPNRouters map", routerName, dpId);
1036             }
1037         } else {
1038             LOG.debug("addToDpnRoutersMap : Building new DPNRoutersList for the Router {} present in the DPN {} "
1039                     + "ODL-L3VPN : DPNRouters map", routerName, dpId);
1040             DpnRoutersListBuilder dpnRoutersListBuilder = new DpnRoutersListBuilder();
1041             dpnRoutersListBuilder.setDpnId(dpId);
1042             RoutersListBuilder routersListBuilder = new RoutersListBuilder();
1043             routersListBuilder.setRouter(routerName);
1044             dpnRoutersListBuilder.setRoutersList(Collections.singletonList(routersListBuilder.build()));
1045             writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1046                     getDpnRoutersId(dpId),
1047                     dpnRoutersListBuilder.build(), true);
1048         }
1049     }
1050
1051
1052     public static void removeFromNeutronRouterDpnsMap(DataBroker broker, String routerName, String interfaceName,
1053                                                BigInteger dpId, WriteTransaction writeOperTxn) {
1054         if (dpId.equals(BigInteger.ZERO)) {
1055             LOG.error("removeFromNeutronRouterDpnsMap : Could not retrieve dp id for interface {} to handle router {} "
1056                     + "dissociation model", interfaceName, routerName);
1057             return;
1058         }
1059         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1060         Optional<DpnVpninterfacesList> optionalRouterDpnList =
1061                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1062                         LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1063         if (optionalRouterDpnList.isPresent()) {
1064             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1065                 .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces> routerInterfaces =
1066                 optionalRouterDpnList.get().getRouterInterfaces();
1067             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1068                 .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces routerInterface =
1069                 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(interfaceName))
1070                     .setInterface(interfaceName).build();
1071             if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1072                 if (routerInterfaces.isEmpty()) {
1073                     writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1074                 } else {
1075                     writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1076                         org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1077                             .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
1078                         new RouterInterfacesKey(interfaceName)));
1079                 }
1080             }
1081         }
1082     }
1083
1084     public static void removeFromNeutronRouterDpnsMap(DataBroker broker, String routerName,
1085                                                BigInteger dpId, WriteTransaction writeOperTxn) {
1086         if (dpId.equals(BigInteger.ZERO)) {
1087             LOG.warn("removeFromNeutronRouterDpnsMap : DPN ID is invalid for the router {} ", routerName);
1088             return;
1089         }
1090
1091         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1092         Optional<DpnVpninterfacesList> optionalRouterDpnList =
1093                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1094                         LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1095         if (optionalRouterDpnList.isPresent()) {
1096             LOG.debug("removeFromNeutronRouterDpnsMap : Removing the dpn-vpninterfaces-list from the "
1097                     + "odl-l3vpn:neutron-router-dpns model for the router {}", routerName);
1098             writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1099         } else {
1100             LOG.debug("removeFromNeutronRouterDpnsMap : dpn-vpninterfaces-list does not exist in the "
1101                     + "odl-l3vpn:neutron-router-dpns model for the router {}", routerName);
1102         }
1103     }
1104
1105     public static void removeFromNeutronRouterDpnsMap(DataBroker broker, String routerName, String vpnInterfaceName,
1106                                                OdlInterfaceRpcService ifaceMgrRpcService,
1107                                                WriteTransaction writeOperTxn) {
1108         BigInteger dpId = getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1109         if (dpId.equals(BigInteger.ZERO)) {
1110             LOG.debug("removeFromNeutronRouterDpnsMap : Could not retrieve dp id for interface {} to handle router {}"
1111                     + " dissociation model", vpnInterfaceName, routerName);
1112             return;
1113         }
1114         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1115         Optional<DpnVpninterfacesList> optionalRouterDpnList =
1116                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1117                         LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1118         if (optionalRouterDpnList.isPresent()) {
1119             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns
1120                 .router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces> routerInterfaces =
1121                 optionalRouterDpnList.get().getRouterInterfaces();
1122             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn
1123                 .list.dpn.vpninterfaces.list.RouterInterfaces routerInterface =
1124                 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName))
1125                     .setInterface(vpnInterfaceName).build();
1126
1127             if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1128                 if (routerInterfaces.isEmpty()) {
1129                     if (writeOperTxn != null) {
1130                         writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1131                     } else {
1132                         MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1133                     }
1134                 } else {
1135                     if (writeOperTxn != null) {
1136                         writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1137                             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1138                                 .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
1139                             new RouterInterfacesKey(vpnInterfaceName)));
1140                     } else {
1141                         MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1142                             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron
1143                                 .router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
1144                             new RouterInterfacesKey(vpnInterfaceName)));
1145                     }
1146                 }
1147             }
1148         }
1149     }
1150
1151     public static void removeFromDpnRoutersMap(DataBroker broker, String routerName, String vpnInterfaceName,
1152                                         OdlInterfaceRpcService ifaceMgrRpcService, WriteTransaction writeOperTxn) {
1153         BigInteger dpId = getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1154         if (dpId.equals(BigInteger.ZERO)) {
1155             LOG.debug("removeFromDpnRoutersMap : removeFromDpnRoutersMap() : "
1156                 + "Could not retrieve DPN ID for interface {} to handle router {} dissociation model",
1157                 vpnInterfaceName, routerName);
1158             return;
1159         }
1160         removeFromDpnRoutersMap(broker, routerName, vpnInterfaceName, dpId, ifaceMgrRpcService, writeOperTxn);
1161     }
1162
1163     static void removeFromDpnRoutersMap(DataBroker broker, String routerName, String vpnInterfaceName,
1164                                         BigInteger curDpnId,
1165                                         OdlInterfaceRpcService ifaceMgrRpcService, WriteTransaction writeOperTxn) {
1166         /*
1167             1) Get the DpnRoutersList for the DPN.
1168             2) Get the RoutersList identifier for the DPN and router.
1169             3) Get the VPN interfaces for the router (routerList) through which it is connected to the DPN.
1170             4) If the removed VPN interface is the only interface through which the router is connected to the DPN,
1171              then remove RouterList.
1172          */
1173
1174         LOG.debug("removeFromDpnRoutersMap() : Removing the DPN {} and router {} for the Interface {}"
1175             + " in the ODL-L3VPN : DPNRouters map", curDpnId, routerName, vpnInterfaceName);
1176
1177         //Get the dpn-routers-list instance for the current DPN.
1178         InstanceIdentifier<DpnRoutersList> dpnRoutersListIdentifier = getDpnRoutersId(curDpnId);
1179         Optional<DpnRoutersList> dpnRoutersListData =
1180                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1181                         LogicalDatastoreType.OPERATIONAL, dpnRoutersListIdentifier);
1182
1183         if (dpnRoutersListData == null || !dpnRoutersListData.isPresent()) {
1184             LOG.error("removeFromDpnRoutersMap : dpn-routers-list is not present for DPN {} "
1185                     + "in the ODL-L3VPN:dpn-routers model", curDpnId);
1186             return;
1187         }
1188
1189         //Get the routers-list instance for the router on the current DPN only
1190         InstanceIdentifier<RoutersList> routersListIdentifier = getRoutersList(curDpnId, routerName);
1191         Optional<RoutersList> routersListData =
1192                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1193                         LogicalDatastoreType.OPERATIONAL, routersListIdentifier);
1194
1195         if (routersListData == null || !routersListData.isPresent()) {
1196             LOG.error("removeFromDpnRoutersMap : routers-list is not present for the DPN {} "
1197                     + "in the ODL-L3VPN:dpn-routers model",
1198                 curDpnId);
1199             return;
1200         }
1201
1202         LOG.debug("removeFromDpnRoutersMap : Get the interfaces for the router {} "
1203                 + "from the NeutronVPN - router-interfaces-map", routerName);
1204         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router
1205             .interfaces.map.RouterInterfaces> routerInterfacesId = getRoutersInterfacesIdentifier(routerName);
1206         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map
1207                 .RouterInterfaces> routerInterfacesData =
1208                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1209                         LogicalDatastoreType.CONFIGURATION, routerInterfacesId);
1210
1211         if (routerInterfacesData == null || !routerInterfacesData.isPresent()) {
1212             LOG.debug("removeFromDpnRoutersMap : Unable to get the routers list for the DPN {}. Possibly all subnets "
1213                     + "removed from router {} OR Router {} has been deleted. Hence DPN router model WILL be cleared ",
1214                 curDpnId, routerName, routerName);
1215             writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routersListIdentifier);
1216             return;
1217         }
1218
1219         //Get the VM interfaces for the router on the current DPN only.
1220         List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces
1221             .map.router.interfaces.Interfaces> vmInterfaces = routerInterfacesData.get().getInterfaces();
1222         if (vmInterfaces == null) {
1223             LOG.debug("removeFromDpnRoutersMap : VM interfaces are not present for the router {} in the "
1224                 + "NeutronVPN - router-interfaces-map", routerName);
1225             return;
1226         }
1227
1228         // If the removed VPN interface is the only interface through which the router is connected to the DPN,
1229         // then remove RouterList.
1230         for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map
1231                  .router.interfaces.Interfaces vmInterface : vmInterfaces) {
1232             String vmInterfaceName = vmInterface.getInterfaceId();
1233             BigInteger vmDpnId = getDpnForInterface(ifaceMgrRpcService, vmInterfaceName);
1234             if (vmDpnId.equals(BigInteger.ZERO) || !vmDpnId.equals(curDpnId)) {
1235                 LOG.debug("removeFromDpnRoutersMap : DPN ID {} for the removed interface {} is not the same as that of "
1236                         + "the DPN ID {} for the checked interface {}",
1237                     curDpnId, vpnInterfaceName, vmDpnId, vmInterfaceName);
1238                 continue;
1239             }
1240             if (!vmInterfaceName.equalsIgnoreCase(vpnInterfaceName)) {
1241                 LOG.info("removeFromDpnRoutersMap : Router {} is present in the DPN {} through the other interface {} "
1242                     + "Hence DPN router model WOULD NOT be cleared", routerName, curDpnId, vmInterfaceName);
1243                 return;
1244             }
1245         }
1246         LOG.debug("removeFromDpnRoutersMap : Router {} is present in the DPN {} only through the interface {} "
1247             + "Hence DPN router model WILL be cleared. Possibly last VM for the router "
1248             + "deleted in the DPN", routerName, curDpnId, vpnInterfaceName);
1249         writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routersListIdentifier);
1250     }
1251
1252     private static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
1253         .rev150602.router.interfaces.map.RouterInterfaces> getRoutersInterfacesIdentifier(String routerName) {
1254         return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
1255             .rev150602.RouterInterfacesMap.class)
1256             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router
1257                     .interfaces.map.RouterInterfaces.class,
1258                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router
1259                     .interfaces.map.RouterInterfacesKey(new Uuid(routerName))).build();
1260     }
1261
1262     private static InstanceIdentifier<RoutersList> getRoutersList(BigInteger dpnId, String routerName) {
1263         return InstanceIdentifier.builder(DpnRouters.class)
1264             .child(DpnRoutersList.class, new DpnRoutersListKey(dpnId))
1265             .child(RoutersList.class, new RoutersListKey(routerName)).build();
1266     }
1267
1268     public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
1269         BigInteger nodeId = BigInteger.ZERO;
1270         try {
1271             GetDpidFromInterfaceInput
1272                 dpIdInput =
1273                 new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
1274             Future<RpcResult<GetDpidFromInterfaceOutput>>
1275                 dpIdOutput =
1276                 interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
1277             RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
1278             if (dpIdResult.isSuccessful()) {
1279                 nodeId = dpIdResult.getResult().getDpid();
1280             } else {
1281                 LOG.debug("removeFromDpnRoutersMap : Could not retrieve DPN Id for interface {}", ifName);
1282             }
1283         } catch (NullPointerException | InterruptedException | ExecutionException e) {
1284             LOG.error("removeFromDpnRoutersMap : Exception when getting dpn for interface {}", ifName, e);
1285         }
1286         return nodeId;
1287     }
1288
1289     @Nonnull
1290     public static List<ActionInfo> getEgressActionsForInterface(OdlInterfaceRpcService odlInterfaceRpcService,
1291                                                                 ItmRpcService itmRpcService,
1292                                                                 IInterfaceManager interfaceManager, String ifName,
1293                                                                 Long tunnelKey) {
1294         return getEgressActionsForInterface(odlInterfaceRpcService, itmRpcService, interfaceManager,
1295                 ifName, tunnelKey, 0);
1296     }
1297
1298     @Nonnull
1299     public static List<ActionInfo> getEgressActionsForInterface(OdlInterfaceRpcService odlInterfaceRpcService,
1300                                                                 ItmRpcService itmRpcService,
1301                                                                 IInterfaceManager interfaceManager,
1302                                                                 String ifName, Long tunnelKey, int pos) {
1303         LOG.debug("getEgressActionsForInterface : called for interface {}", ifName);
1304         GetEgressActionsForInterfaceInputBuilder egressActionsIfmBuilder =
1305                 new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName);
1306         GetEgressActionsForTunnelInputBuilder egressActionsItmBuilder = new GetEgressActionsForTunnelInputBuilder()
1307             .setIntfName(ifName);
1308         if (tunnelKey != null) {
1309             egressActionsIfmBuilder.setTunnelKey(tunnelKey);
1310             egressActionsItmBuilder.setTunnelKey(tunnelKey);
1311         }
1312
1313         try {
1314             RpcResult<GetEgressActionsForTunnelOutput> rpcResultItm = null;
1315             RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = null;
1316             List<Action> actions = Collections.emptyList();
1317             if (interfaceManager.isItmDirectTunnelsEnabled()) {
1318                 rpcResultItm =
1319                         itmRpcService.getEgressActionsForTunnel(egressActionsItmBuilder.build()).get();
1320             } else {
1321                 rpcResult =
1322                         odlInterfaceRpcService.getEgressActionsForInterface(egressActionsIfmBuilder.build()).get();
1323             }
1324
1325             if (!interfaceManager.isItmDirectTunnelsEnabled() && rpcResult != null) {
1326                 if (!rpcResult.isSuccessful()) {
1327                     LOG.error("getEgressActionsForInterface : RPC Call to Get egress actions for interface {} "
1328                             + "returned with Errors {}", ifName, rpcResult.getErrors());
1329                 } else {
1330                     actions = rpcResult.getResult().getAction();
1331                 }
1332             } else if (interfaceManager.isItmDirectTunnelsEnabled() && rpcResultItm != null) {
1333                 if (!rpcResultItm.isSuccessful()) {
1334                     LOG.error("getEgressActionsForTunnels : RPC Call to Get egress actions for Tunnels {} "
1335                             + "returned with Errors {}", ifName, rpcResultItm.getErrors());
1336                 } else {
1337                     actions = rpcResultItm.getResult().getAction();
1338                 }
1339             }
1340             List<ActionInfo> listActionInfo = new ArrayList<>();
1341             for (Action action : actions) {
1342                 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action
1343                     actionClass = action.getAction();
1344                 if (actionClass instanceof OutputActionCase) {
1345                     listActionInfo.add(new ActionOutput(pos++,
1346                         ((OutputActionCase) actionClass).getOutputAction().getOutputNodeConnector()));
1347                 } else if (actionClass instanceof PushVlanActionCase) {
1348                     listActionInfo.add(new ActionPushVlan(pos++));
1349                 } else if (actionClass instanceof SetFieldCase) {
1350                     if (((SetFieldCase) actionClass).getSetField().getVlanMatch() != null) {
1351                         int vlanVid = ((SetFieldCase) actionClass).getSetField().getVlanMatch().getVlanId()
1352                             .getVlanId().getValue();
1353                         listActionInfo.add(new ActionSetFieldVlanVid(pos++, vlanVid));
1354                     }
1355                 } else if (actionClass instanceof NxActionResubmitRpcAddGroupCase) {
1356                     Short tableId = ((NxActionResubmitRpcAddGroupCase) actionClass).getNxResubmit().getTable();
1357                     listActionInfo.add(new ActionNxResubmit(pos++, tableId));
1358                 } else if (actionClass instanceof NxActionRegLoadNodesNodeTableFlowApplyActionsCase) {
1359                     NxRegLoad nxRegLoad =
1360                         ((NxActionRegLoadNodesNodeTableFlowApplyActionsCase) actionClass).getNxRegLoad();
1361                     listActionInfo.add(new ActionRegLoad(pos++, NxmNxReg6.class, nxRegLoad.getDst().getStart(),
1362                         nxRegLoad.getDst().getEnd(), nxRegLoad.getValue().longValue()));
1363                 }
1364             }
1365             return listActionInfo;
1366         } catch (InterruptedException | ExecutionException e) {
1367             LOG.error("Exception when egress actions for interface {}", ifName, e);
1368         }
1369         LOG.error("Error when getting egress actions for interface {}", ifName);
1370         return Collections.emptyList();
1371     }
1372
1373     public static Port getNeutronPortForRouterGetewayIp(DataBroker broker, IpAddress targetIP) {
1374         return getNeutronPortForIp(broker, targetIP, NeutronConstants.DEVICE_OWNER_GATEWAY_INF);
1375     }
1376
1377     @Nonnull
1378     public static List<Port> getNeutronPorts(DataBroker broker) {
1379         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports>
1380             portsIdentifier = InstanceIdentifier.create(Neutron.class)
1381             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports.class);
1382         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports>
1383                 portsOptional =
1384                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1385                         LogicalDatastoreType.CONFIGURATION, portsIdentifier);
1386
1387         if (!portsOptional.isPresent() || portsOptional.get().getPort() == null) {
1388             LOG.error("getNeutronPorts : No neutron ports found");
1389             return Collections.emptyList();
1390         }
1391
1392         return portsOptional.get().getPort();
1393     }
1394
1395     public static Port getNeutronPortForIp(DataBroker broker,
1396                                            IpAddress targetIP, String deviceType) {
1397         List<Port> ports = getNeutronPorts(
1398             broker);
1399
1400         for (Port port : ports) {
1401             if (deviceType.equals(port.getDeviceOwner()) && port.getFixedIps() != null) {
1402                 for (FixedIps ip : port.getFixedIps()) {
1403                     if (Objects.equals(ip.getIpAddress(), targetIP)) {
1404                         return port;
1405                     }
1406                 }
1407             }
1408         }
1409         LOG.error("getNeutronPortForIp : Neutron Port missing for IP:{} DeviceType:{}", targetIP, deviceType);
1410         return null;
1411     }
1412
1413     public static Uuid getSubnetIdForFloatingIp(Port port, IpAddress targetIP) {
1414         if (port == null) {
1415             LOG.error("getSubnetIdForFloatingIp : port is null");
1416             return null;
1417         }
1418         for (FixedIps ip : port.getFixedIps()) {
1419             if (Objects.equals(ip.getIpAddress(), targetIP)) {
1420                 return ip.getSubnetId();
1421             }
1422         }
1423         LOG.error("getSubnetIdForFloatingIp : No Fixed IP configured for targetIP:{}", targetIP);
1424         return null;
1425     }
1426
1427     public static Subnetmap getSubnetMap(DataBroker broker, Uuid subnetId) {
1428         InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier.builder(Subnetmaps.class)
1429             .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
1430         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1431                 LogicalDatastoreType.CONFIGURATION, subnetmapId).orNull();
1432     }
1433
1434     @Nonnull
1435     public static List<Uuid> getSubnetIdsFromNetworkId(DataBroker broker, Uuid networkId) {
1436         InstanceIdentifier<NetworkMap> id = InstanceIdentifier.builder(NetworkMaps.class)
1437             .child(NetworkMap.class, new NetworkMapKey(networkId)).build();
1438         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1439                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(NetworkMap::getSubnetIdList).orElse(
1440                 Collections.emptyList());
1441     }
1442
1443     public static String getSubnetGwMac(DataBroker broker, Uuid subnetId, String vpnName) {
1444         if (subnetId == null) {
1445             LOG.error("getSubnetGwMac : subnetID is null");
1446             return null;
1447         }
1448
1449         InstanceIdentifier<Subnet> subnetInst = InstanceIdentifier.create(Neutron.class).child(Subnets.class)
1450             .child(Subnet.class, new SubnetKey(subnetId));
1451         Optional<Subnet> subnetOpt =
1452                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1453                         LogicalDatastoreType.CONFIGURATION, subnetInst);
1454         if (!subnetOpt.isPresent()) {
1455             LOG.error("getSubnetGwMac : unable to obtain Subnet for id : {}", subnetId);
1456             return null;
1457         }
1458
1459         IpAddress gatewayIp = subnetOpt.get().getGatewayIp();
1460         if (gatewayIp == null) {
1461             LOG.warn("getSubnetGwMac : No GW ip found for subnet {}", subnetId.getValue());
1462             return null;
1463         }
1464
1465         InstanceIdentifier<VpnPortipToPort> portIpInst = InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
1466             .child(VpnPortipToPort.class, new VpnPortipToPortKey(gatewayIp.getIpv4Address().getValue(), vpnName))
1467             .build();
1468         Optional<VpnPortipToPort> portIpToPortOpt =
1469                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1470                         LogicalDatastoreType.CONFIGURATION, portIpInst);
1471         if (portIpToPortOpt.isPresent()) {
1472             return portIpToPortOpt.get().getMacAddress();
1473         }
1474
1475         InstanceIdentifier<LearntVpnVipToPort> learntIpInst = InstanceIdentifier.builder(LearntVpnVipToPortData.class)
1476             .child(LearntVpnVipToPort.class, new LearntVpnVipToPortKey(gatewayIp.getIpv4Address().getValue(), vpnName))
1477             .build();
1478         Optional<LearntVpnVipToPort> learntIpToPortOpt =
1479                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1480                         LogicalDatastoreType.OPERATIONAL, learntIpInst);
1481         if (learntIpToPortOpt.isPresent()) {
1482             return learntIpToPortOpt.get().getMacAddress();
1483         }
1484
1485         LOG.info("getSubnetGwMac : No resolution was found to GW ip {} in subnet {}", gatewayIp, subnetId.getValue());
1486         return null;
1487     }
1488
1489     public static boolean isIPv6Subnet(String prefix) {
1490         return new IpPrefix(prefix.toCharArray()).getIpv6Prefix() != null;
1491     }
1492
1493     static InstanceIdentifier<DpnRoutersList> getDpnRoutersId(BigInteger dpnId) {
1494         return InstanceIdentifier.builder(DpnRouters.class)
1495             .child(DpnRoutersList.class, new DpnRoutersListKey(dpnId)).build();
1496     }
1497
1498     static InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1499         return InstanceIdentifier.builder(NeutronRouterDpns.class)
1500             .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1501             .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1502     }
1503
1504     static InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1505         return InstanceIdentifier.builder(NeutronRouterDpns.class)
1506             .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1507     }
1508
1509     protected static String getFloatingIpPortMacFromFloatingIpId(DataBroker broker, Uuid floatingIpId) {
1510         InstanceIdentifier<FloatingIpIdToPortMapping> id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
1511         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1512                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
1513                 FloatingIpIdToPortMapping::getFloatingIpPortMacAddress).orElse(null);
1514     }
1515
1516     protected static Uuid getFloatingIpPortSubnetIdFromFloatingIpId(DataBroker broker, Uuid floatingIpId) {
1517         InstanceIdentifier<FloatingIpIdToPortMapping> id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
1518         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1519                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
1520                 FloatingIpIdToPortMapping::getFloatingIpPortSubnetId).orElse(null);
1521     }
1522
1523     static InstanceIdentifier<FloatingIpIdToPortMapping> buildfloatingIpIdToPortMappingIdentifier(Uuid floatingIpId) {
1524         return InstanceIdentifier.builder(FloatingIpPortInfo.class).child(FloatingIpIdToPortMapping.class, new
1525             FloatingIpIdToPortMappingKey(floatingIpId)).build();
1526     }
1527
1528     static Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
1529         InstanceIdentifier<Interface> ifStateId =
1530             buildStateInterfaceId(interfaceName);
1531         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1532                 LogicalDatastoreType.OPERATIONAL, ifStateId).orNull();
1533     }
1534
1535     static InstanceIdentifier<Interface> buildStateInterfaceId(String interfaceName) {
1536         InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
1537             InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
1538                 .interfaces.rev140508.InterfacesState.class)
1539                 .child(Interface.class,
1540                     new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
1541                         .interfaces.state.InterfaceKey(interfaceName));
1542         InstanceIdentifier<Interface> id = idBuilder.build();
1543         return id;
1544     }
1545
1546     public static Routers getRoutersFromConfigDS(DataBroker dataBroker, String routerName) {
1547         InstanceIdentifier<Routers> routerIdentifier = NatUtil.buildRouterIdentifier(routerName);
1548         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1549                 LogicalDatastoreType.CONFIGURATION, routerIdentifier).orNull();
1550     }
1551
1552     static void createRouterIdsConfigDS(DataBroker dataBroker, long routerId, String routerName) {
1553         if (routerId == NatConstants.INVALID_ID) {
1554             LOG.error("createRouterIdsConfigDS : invalid routerId for routerName {}", routerName);
1555             return;
1556         }
1557         RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(routerId))
1558             .setRouterId(routerId).setRouterName(routerName).build();
1559         MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, buildRouterIdentifier(routerId), rtrs);
1560     }
1561
1562     static FlowEntity buildDefaultNATFlowEntityForExternalSubnet(BigInteger dpId, long vpnId, String subnetId,
1563             IdManagerService idManager) {
1564         InetAddress defaultIP = null;
1565         try {
1566             defaultIP = InetAddress.getByName("0.0.0.0");
1567         } catch (UnknownHostException e) {
1568             LOG.error("buildDefaultNATFlowEntityForExternalSubnet : Failed to build FIB Table Flow for "
1569                     + "Default Route to NAT.", e);
1570             return null;
1571         }
1572
1573         List<MatchInfo> matches = new ArrayList<>();
1574         matches.add(MatchEthernetType.IPV4);
1575         //add match for vrfid
1576         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
1577
1578         List<InstructionInfo> instructions = new ArrayList<>();
1579         List<ActionInfo> actionsInfo = new ArrayList<>();
1580         long groupId = createGroupId(NatUtil.getGroupIdKey(subnetId), idManager);
1581         actionsInfo.add(new ActionGroup(groupId));
1582         String flowRef = getFlowRef(dpId, NwConstants.L3_FIB_TABLE, defaultIP, vpnId);
1583         instructions.add(new InstructionApplyActions(actionsInfo));
1584         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_FIB_TABLE, flowRef,
1585                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
1586                 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
1587         return flowEntity;
1588     }
1589
1590     static String getExtGwMacAddFromRouterId(DataBroker broker, long routerId) {
1591         String routerName = getRouterName(broker, routerId);
1592         if (routerName == null) {
1593             LOG.error("getExtGwMacAddFromRouterId : empty routerName received");
1594             return null;
1595         }
1596         return getExtGwMacAddFromRouterName(broker, routerName);
1597     }
1598
1599     static String getExtGwMacAddFromRouterName(DataBroker broker, String routerName) {
1600         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerName);
1601         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1602                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(Routers::getExtGwMacAddress).orElse(null);
1603     }
1604
1605
1606     static InstanceIdentifier<Router> buildNeutronRouterIdentifier(Uuid routerUuid) {
1607         InstanceIdentifier<Router> routerInstanceIdentifier = InstanceIdentifier.create(Neutron.class)
1608              .child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers.class)
1609              .child(Router.class, new RouterKey(routerUuid));
1610         return routerInstanceIdentifier;
1611     }
1612
1613     public static String getNeutronRouterNamebyUuid(DataBroker broker, Uuid routerUuid) {
1614         InstanceIdentifier<Router> neutronRouterIdentifier = NatUtil.buildNeutronRouterIdentifier(routerUuid);
1615         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1616                 LogicalDatastoreType.CONFIGURATION, neutronRouterIdentifier).toJavaUtil().map(Router::getName).orElse(
1617                 null);
1618     }
1619
1620     @Nonnull
1621     public static List<Ports> getFloatingIpPortsForRouter(DataBroker broker, Uuid routerUuid) {
1622         InstanceIdentifier<RouterPorts> routerPortsIdentifier = getRouterPortsId(routerUuid.getValue());
1623         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1624                 LogicalDatastoreType.CONFIGURATION,
1625                 routerPortsIdentifier).toJavaUtil().map(RouterPorts::getPorts).orElse(Collections.emptyList());
1626     }
1627
1628     @Nonnull
1629     public static List<Uuid> getRouterUuIdsForVpn(DataBroker broker, Uuid vpnUuid) {
1630         InstanceIdentifier<ExternalNetworks> externalNwIdentifier = InstanceIdentifier.create(ExternalNetworks.class);
1631         Optional<ExternalNetworks> externalNwData =
1632                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1633                         LogicalDatastoreType.CONFIGURATION, externalNwIdentifier);
1634         if (externalNwData.isPresent()) {
1635             for (Networks externalNw : externalNwData.get().getNetworks()) {
1636                 if (externalNw.getVpnid() != null && externalNw.getVpnid().equals(vpnUuid)) {
1637                     return externalNw.getRouterIds();
1638                 }
1639             }
1640         }
1641         return Collections.emptyList();
1642     }
1643
1644     public static boolean isIpInSubnet(String ipAddress, String start, String end) {
1645
1646         try {
1647             long ipLo = ipToLong(InetAddress.getByName(start));
1648             long ipHi = ipToLong(InetAddress.getByName(end));
1649             long ipToTest = ipToLong(InetAddress.getByName(ipAddress));
1650             return ipToTest >= ipLo && ipToTest <= ipHi;
1651         } catch (UnknownHostException e) {
1652             LOG.error("isIpInSubnet : failed for IP {}", ipAddress, e);
1653             return false;
1654         }
1655     }
1656
1657     @Nonnull
1658     public static Collection<Uuid> getExternalSubnetIdsFromExternalIps(List<ExternalIps> externalIps) {
1659         if (externalIps == null) {
1660             return Collections.emptySet();
1661         }
1662
1663         return externalIps.stream().map(ExternalIps::getSubnetId).collect(Collectors.toSet());
1664     }
1665
1666     @Nonnull
1667     public static Collection<Uuid> getExternalSubnetIdsForRouter(DataBroker dataBroker, String routerName) {
1668         if (routerName == null) {
1669             LOG.error("getExternalSubnetIdsForRouter : empty routerName received");
1670             return Collections.emptySet();
1671         }
1672
1673         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerName);
1674         Optional<Routers> routerData =
1675                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1676                         LogicalDatastoreType.CONFIGURATION, id);
1677         if (routerData.isPresent()) {
1678             return NatUtil.getExternalSubnetIdsFromExternalIps(routerData.get().getExternalIps());
1679         } else {
1680             LOG.warn("getExternalSubnetIdsForRouter : No external router data for router {}", routerName);
1681             return Collections.emptySet();
1682         }
1683     }
1684
1685     @Nonnull
1686     protected static Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
1687         .subnets.Subnets> getOptionalExternalSubnets(DataBroker dataBroker, Uuid subnetId) {
1688         if (subnetId == null) {
1689             LOG.warn("getOptionalExternalSubnets : subnetId is null");
1690             return Optional.absent();
1691         }
1692
1693         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice
1694             .rev160111.external.subnets.Subnets> subnetsIdentifier =
1695                 InstanceIdentifier.builder(ExternalSubnets.class)
1696                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice
1697                         .rev160111.external.subnets.Subnets.class, new SubnetsKey(subnetId)).build();
1698         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1699                 LogicalDatastoreType.CONFIGURATION, subnetsIdentifier);
1700     }
1701
1702     protected static long getExternalSubnetVpnId(DataBroker dataBroker, Uuid subnetId) {
1703         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
1704             .subnets.Subnets> optionalExternalSubnets = NatUtil.getOptionalExternalSubnets(dataBroker,
1705                    subnetId);
1706         if (optionalExternalSubnets.isPresent()) {
1707             return NatUtil.getVpnId(dataBroker, subnetId.getValue());
1708         }
1709
1710         return NatConstants.INVALID_ID;
1711     }
1712
1713     protected static long getExternalSubnetVpnIdForRouterExternalIp(DataBroker dataBroker, String externalIpAddress,
1714             Routers router) {
1715         Uuid externalSubnetId = NatUtil.getExternalSubnetForRouterExternalIp(externalIpAddress, router);
1716         if (externalSubnetId != null) {
1717             return NatUtil.getExternalSubnetVpnId(dataBroker,externalSubnetId);
1718         }
1719
1720         return NatConstants.INVALID_ID;
1721     }
1722
1723     protected static Uuid getExternalSubnetForRouterExternalIp(String externalIpAddress, Routers router) {
1724         externalIpAddress = validateAndAddNetworkMask(externalIpAddress);
1725         List<ExternalIps> externalIps = router.getExternalIps();
1726         for (ExternalIps extIp : externalIps) {
1727             String extIpString = validateAndAddNetworkMask(extIp.getIpAddress());
1728             if (extIpString.equals(externalIpAddress)) {
1729                 return extIp.getSubnetId();
1730             }
1731         }
1732         LOG.warn("getExternalSubnetForRouterExternalIp : Missing External Subnet for Ip:{}", externalIpAddress);
1733         return null;
1734     }
1735
1736     private static long ipToLong(InetAddress ip) {
1737         byte[] octets = ip.getAddress();
1738         long result = 0;
1739         for (byte octet : octets) {
1740             result <<= 8;
1741             result |= octet & 0xff;
1742         }
1743         return result;
1744     }
1745
1746     @Nonnull
1747     static List<String> getIpsListFromExternalIps(@Nullable List<ExternalIps> externalIps) {
1748         if (externalIps == null) {
1749             return Collections.emptyList();
1750         }
1751
1752         return externalIps.stream().map(ExternalIps::getIpAddress).collect(Collectors.toList());
1753     }
1754
1755     // elan-instances config container
1756     public static ElanInstance getElanInstanceByName(String elanInstanceName, DataBroker broker) {
1757         InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
1758         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1759                 LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orNull();
1760     }
1761
1762     public static InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
1763         return InstanceIdentifier.builder(ElanInstances.class)
1764                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
1765     }
1766
1767     public static long getTunnelIdForNonNaptToNaptFlow(DataBroker dataBroker, IElanService elanManager,
1768             IdManagerService idManager, long routerId, String routerName) {
1769         if (elanManager.isOpenStackVniSemanticsEnforced()) {
1770             // Router VNI will be set as tun_id if OpenStackSemantics is enabled
1771             return NatOverVxlanUtil.getRouterVni(idManager, routerName, routerId).longValue();
1772         } else {
1773             return NatEvpnUtil.getTunnelIdForRouter(idManager, dataBroker, routerName, routerId);
1774         }
1775     }
1776
1777     public static void makePreDnatToSnatTableEntry(IMdsalApiManager mdsalManager, BigInteger naptDpnId,
1778             short tableId, WriteTransaction writeFlowTx) {
1779         LOG.debug("makePreDnatToSnatTableEntry : Create Pre-DNAT table {} --> table {} flow on NAPT DpnId {} ",
1780                 NwConstants.PDNAT_TABLE, tableId, naptDpnId);
1781
1782         List<Instruction> preDnatToSnatInstructions = new ArrayList<>();
1783         preDnatToSnatInstructions.add(new InstructionGotoTable(tableId).buildInstruction(0));
1784         List<MatchInfo> matches = new ArrayList<>();
1785         matches.add(MatchEthernetType.IPV4);
1786         String flowRef = getFlowRefPreDnatToSnat(naptDpnId, NwConstants.PDNAT_TABLE, "PreDNATToSNAT");
1787         Flow preDnatToSnatTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.PDNAT_TABLE,flowRef,
1788                 5, flowRef, 0, 0,  NwConstants.COOKIE_DNAT_TABLE,
1789                 matches, preDnatToSnatInstructions);
1790
1791         mdsalManager.addFlowToTx(naptDpnId, preDnatToSnatTableFlowEntity, writeFlowTx);
1792         LOG.debug("makePreDnatToSnatTableEntry : Successfully installed Pre-DNAT flow {} on NAPT DpnId {} ",
1793                 preDnatToSnatTableFlowEntity,  naptDpnId);
1794     }
1795
1796     public static void removePreDnatToSnatTableEntry(IMdsalApiManager mdsalManager, BigInteger naptDpnId,
1797                                                      WriteTransaction removeFlowInvTx) {
1798         LOG.debug("removePreDnatToSnatTableEntry : Remove Pre-DNAT table {} --> table {} flow on NAPT DpnId {} ",
1799                 NwConstants.PDNAT_TABLE, NwConstants.INBOUND_NAPT_TABLE, naptDpnId);
1800         String flowRef = getFlowRefPreDnatToSnat(naptDpnId, NwConstants.PDNAT_TABLE, "PreDNATToSNAT");
1801         Flow preDnatToSnatTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.PDNAT_TABLE,flowRef,
1802                 5, flowRef, 0, 0,  NwConstants.COOKIE_DNAT_TABLE, null, null);
1803         mdsalManager.removeFlowToTx(naptDpnId, preDnatToSnatTableFlowEntity, removeFlowInvTx);
1804         LOG.debug("removePreDnatToSnatTableEntry: Successfully removed Pre-DNAT flow {} on NAPT DpnId = {}",
1805                 preDnatToSnatTableFlowEntity, naptDpnId);
1806     }
1807
1808     private static String getFlowRefPreDnatToSnat(BigInteger dpnId, short tableId, String uniqueId) {
1809         return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId
1810                 + NwConstants.FLOWID_SEPARATOR + uniqueId;
1811     }
1812
1813     public static Boolean isFloatingIpPresentForDpn(DataBroker dataBroker, BigInteger dpnId, String rd,
1814                                                     String vpnName, String externalIp,
1815                                                     Boolean isMoreThanOneFipCheckOnDpn) {
1816         InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
1817         Optional<VpnToDpnList> dpnInVpn = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
1818         if (dpnInVpn.isPresent()) {
1819             LOG.debug("isFloatingIpPresentForDpn : vpn-to-dpn-list is not empty for vpnName {}, dpn id {}, "
1820                     + "rd {} and floatingIp {}", vpnName, dpnId, rd, externalIp);
1821             try {
1822                 List<IpAddresses> ipAddressList = dpnInVpn.get().getIpAddresses();
1823                 if (ipAddressList != null && !ipAddressList.isEmpty()) {
1824                     int floatingIpPresentCount = 0;
1825                     for (IpAddresses ipAddress: ipAddressList) {
1826                         if (!ipAddress.getIpAddress().equals(externalIp)
1827                                 && IpAddresses.IpAddressSource.FloatingIP.equals(ipAddress.getIpAddressSource())) {
1828                             floatingIpPresentCount++;
1829                             //Add tunnel table check
1830                             if (isMoreThanOneFipCheckOnDpn && floatingIpPresentCount > 1) {
1831                                 return Boolean.TRUE;
1832                             }
1833                             //Remove tunnel table check
1834                             if (!isMoreThanOneFipCheckOnDpn) {
1835                                 return Boolean.TRUE;
1836                             }
1837                         }
1838                     }
1839                 } else {
1840                     LOG.debug("isFloatingIpPresentForDpn : vpn-to-dpn-list does not contain any floating IP for DPN {}",
1841                            dpnId);
1842                     return Boolean.FALSE;
1843                 }
1844             } catch (NullPointerException e) {
1845                 LOG.error("isFloatingIpPresentForDpn: Exception occurred on getting external IP address from "
1846                         + "vpn-to-dpn-list on Dpn {}", dpnId, e);
1847                 return Boolean.FALSE;
1848             }
1849         }
1850         return Boolean.FALSE;
1851     }
1852
1853     private static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
1854         return InstanceIdentifier.builder(VpnInstanceOpData.class)
1855                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd))
1856                 .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
1857     }
1858
1859     @Nullable
1860     public static String getPrimaryRd(String vpnName, ReadTransaction tx) throws ReadFailedException {
1861         return tx.read(LogicalDatastoreType.CONFIGURATION,
1862                 getVpnInstanceIdentifier(vpnName)).checkedGet().toJavaUtil().map(NatUtil::getPrimaryRd).orElse(null);
1863     }
1864
1865     public static String getPrimaryRd(DataBroker dataBroker, String vpnName) {
1866         InstanceIdentifier<VpnInstance> id  = getVpnInstanceIdentifier(vpnName);
1867         Optional<VpnInstance> vpnInstance =
1868                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1869                         LogicalDatastoreType.CONFIGURATION, id);
1870         if (vpnInstance.isPresent()) {
1871             return getPrimaryRd(vpnInstance.get());
1872         }
1873         return vpnName;
1874     }
1875
1876     public static String getPrimaryRd(VpnInstance vpnInstance) {
1877         List<String> rds = null;
1878         if (vpnInstance != null) {
1879             rds = getListOfRdsFromVpnInstance(vpnInstance);
1880         }
1881         return rds == null || rds.isEmpty() ? vpnInstance.getVpnInstanceName() : rds.get(0);
1882     }
1883
1884     public static InstanceIdentifier<VpnInstance> getVpnInstanceIdentifier(String vpnName) {
1885         return InstanceIdentifier.builder(VpnInstances.class)
1886             .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
1887     }
1888
1889     @Nonnull
1890     public static List<String> getListOfRdsFromVpnInstance(VpnInstance vpnInstance) {
1891         VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
1892         return vpnConfig.getRouteDistinguisher() != null ? new ArrayList<>(
1893                 vpnConfig.getRouteDistinguisher()) : new ArrayList<>();
1894     }
1895
1896     public static long getVpnIdFromExternalSubnet(DataBroker dataBroker, String routerName, String externalIpAddress) {
1897         if (routerName != null) {
1898             Routers extRouter = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
1899             if (extRouter != null) {
1900                 return getExternalSubnetVpnIdForRouterExternalIp(dataBroker, externalIpAddress, extRouter);
1901             }
1902         }
1903
1904         return NatConstants.INVALID_ID;
1905     }
1906
1907     public static String validateAndAddNetworkMask(String ipAddress) {
1908         return ipAddress.contains("/32") ? ipAddress : ipAddress + "/32";
1909     }
1910
1911     public static InstanceIdentifier<VpnInterfaceOpDataEntry> getVpnInterfaceOpDataEntryIdentifier(
1912             String vpnInterfaceName, String vpnName) {
1913         return InstanceIdentifier.builder(VpnInterfaceOpData.class).child(VpnInterfaceOpDataEntry.class,
1914         new VpnInterfaceOpDataEntryKey(vpnInterfaceName, vpnName)).build();
1915     }
1916
1917     public static VpnInstanceOpDataEntry getVpnInstanceOpData(DataBroker broker, String rd) {
1918         InstanceIdentifier<VpnInstanceOpDataEntry> id = NatUtil.getVpnInstanceOpDataIdentifier(rd);
1919         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
1920                  broker, LogicalDatastoreType.OPERATIONAL, id).orNull();
1921     }
1922
1923     public static boolean checkForRoutersWithSameExtNetAndNaptSwitch(DataBroker broker, Uuid networkId,
1924                                                                      String routerName, BigInteger dpnId) {
1925         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
1926         Optional<Networks> networkData = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
1927
1928         if (networkData != null && networkData.isPresent()) {
1929             List<Uuid> routerUuidList = networkData.get().getRouterIds();
1930             if (routerUuidList != null && !routerUuidList.isEmpty()) {
1931                 for (Uuid routerUuid : routerUuidList) {
1932                     String sharedRouterName = routerUuid.getValue();
1933                     if (!routerName.equals(sharedRouterName)) {
1934                         BigInteger swtichDpnId = NatUtil.getPrimaryNaptfromRouterName(broker, sharedRouterName);
1935                         if (swtichDpnId == null) {
1936                             continue;
1937                         } else if (swtichDpnId.equals(dpnId)) {
1938                             LOG.debug("checkForRoutersWithSameExtNetAndNaptSwitch: external-network {} is "
1939                                     + "associated with other active router {} on NAPT switch {}", networkId,
1940                                     sharedRouterName, swtichDpnId);
1941                             return true;
1942                         }
1943                     }
1944                 }
1945             }
1946         }
1947         return false;
1948     }
1949
1950     public static void installRouterGwFlows(ManagedNewTransactionRunner txRunner, IVpnManager vpnManager,
1951             Routers router, BigInteger primarySwitchId, int addOrRemove) {
1952         ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
1953             List<ExternalIps> externalIps = router.getExternalIps();
1954             List<String> externalIpsSting = new ArrayList<>();
1955
1956             if (externalIps.isEmpty()) {
1957                 LOG.error("installRouterGwFlows: setupRouterGwFlows no externalIP present");
1958                 return;
1959             }
1960             for (ExternalIps externalIp : externalIps) {
1961                 externalIpsSting.add(externalIp.getIpAddress());
1962             }
1963             Uuid subnetVpnName = externalIps.get(0).getSubnetId();
1964             if (addOrRemove == NwConstants.ADD_FLOW) {
1965                 vpnManager.addRouterGwMacFlow(router.getRouterName(), router.getExtGwMacAddress(), primarySwitchId,
1966                         router.getNetworkId(), subnetVpnName.getValue(), tx);
1967                 vpnManager.addArpResponderFlowsToExternalNetworkIps(router.getRouterName(), externalIpsSting,
1968                         router.getExtGwMacAddress(), primarySwitchId,
1969                         router.getNetworkId(), tx);
1970             } else {
1971                 vpnManager.removeRouterGwMacFlow(router.getRouterName(), router.getExtGwMacAddress(), primarySwitchId,
1972                         router.getNetworkId(), subnetVpnName.getValue(), tx);
1973                 vpnManager.removeArpResponderFlowsToExternalNetworkIps(router.getRouterName(), externalIpsSting,
1974                         router.getExtGwMacAddress(), primarySwitchId,
1975                         router.getNetworkId());
1976             }
1977         }), LOG, "Error installing router gateway flows");
1978     }
1979
1980     public static CheckedFuture<Void, TransactionCommitFailedException> waitForTransactionToComplete(
1981             WriteTransaction tx) {
1982         CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
1983         try {
1984             futures.get();
1985         } catch (InterruptedException | ExecutionException e) {
1986             LOG.error("Error writing to datastore {}", e);
1987         }
1988         return futures;
1989     }
1990
1991     public static Boolean isOpenStackVniSemanticsEnforcedForGreAndVxlan(IElanService elanManager,
1992                                                                         ProviderTypes extNwProvType) {
1993         if (elanManager.isOpenStackVniSemanticsEnforced() && (extNwProvType == ProviderTypes.GRE
1994                 || extNwProvType == ProviderTypes.VXLAN)) {
1995             return true;
1996         }
1997         return false;
1998     }
1999 }