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