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