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