natservice: drop nullToEmpty and reqNonNullOrElse
[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 javax.annotation.Nonnull;
37 import javax.annotation.Nullable;
38 import org.apache.commons.net.util.SubnetUtils;
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     @Nullable
1105     static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces
1106         .RouterInterface getConfiguredRouterInterface(DataBroker broker, String interfaceName) {
1107         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1108                 LogicalDatastoreType.CONFIGURATION, NatUtil.getRouterInterfaceId(interfaceName)).orNull();
1109     }
1110
1111     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
1112         .router.interfaces.RouterInterface> getRouterInterfaceId(String interfaceName) {
1113         return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight
1114             .netvirt.l3vpn.rev130911.RouterInterfaces.class)
1115             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces
1116                     .RouterInterface.class,
1117                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces
1118                     .RouterInterfaceKey(interfaceName)).build();
1119     }
1120
1121     public static void addToNeutronRouterDpnsMap(String routerName, String interfaceName, BigInteger dpId,
1122         TypedReadWriteTransaction<Operational> operTx) throws ExecutionException, InterruptedException {
1123
1124         if (dpId.equals(BigInteger.ZERO)) {
1125             LOG.warn("addToNeutronRouterDpnsMap : Could not retrieve dp id for interface {} "
1126                     + "to handle router {} association model", interfaceName, routerName);
1127             return;
1128         }
1129
1130         LOG.debug("addToNeutronRouterDpnsMap : Adding the Router {} and DPN {} for the Interface {} in the "
1131                 + "ODL-L3VPN : NeutronRouterDpn map", routerName, dpId, interfaceName);
1132         InstanceIdentifier<DpnVpninterfacesList> dpnVpnInterfacesListIdentifier = getRouterDpnId(routerName, dpId);
1133
1134         Optional<DpnVpninterfacesList> optionalDpnVpninterfacesList = operTx.read(dpnVpnInterfacesListIdentifier).get();
1135         org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns
1136             .router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces routerInterface =
1137             new RouterInterfacesBuilder().withKey(new RouterInterfacesKey(interfaceName))
1138             .setInterface(interfaceName).build();
1139         if (optionalDpnVpninterfacesList.isPresent()) {
1140             LOG.debug("addToNeutronRouterDpnsMap : RouterDpnList already present for the Router {} and DPN {} for the "
1141                     + "Interface {} in the ODL-L3VPN : NeutronRouterDpn map", routerName, dpId, interfaceName);
1142             operTx.merge(dpnVpnInterfacesListIdentifier
1143                     .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1144                             .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
1145                             new RouterInterfacesKey(interfaceName)), routerInterface, CREATE_MISSING_PARENTS);
1146         } else {
1147             LOG.debug("addToNeutronRouterDpnsMap : Building new RouterDpnList for the Router {} and DPN {} for the "
1148                     + "Interface {} in the ODL-L3VPN : NeutronRouterDpn map", routerName, dpId, interfaceName);
1149             RouterDpnListBuilder routerDpnListBuilder = new RouterDpnListBuilder();
1150             routerDpnListBuilder.setRouterId(routerName);
1151             DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1152             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1153                 .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces> routerInterfaces = new ArrayList<>();
1154             routerInterfaces.add(routerInterface);
1155             dpnVpnList.setRouterInterfaces(routerInterfaces);
1156             routerDpnListBuilder.setDpnVpninterfacesList(Collections.singletonList(dpnVpnList.build()));
1157             operTx.merge(getRouterId(routerName), routerDpnListBuilder.build(), CREATE_MISSING_PARENTS);
1158         }
1159     }
1160
1161     public static void addToDpnRoutersMap(String routerName, String interfaceName, BigInteger dpId,
1162         TypedReadWriteTransaction<Operational> operTx) throws ExecutionException, InterruptedException {
1163         if (dpId.equals(BigInteger.ZERO)) {
1164             LOG.error("addToDpnRoutersMap : Could not retrieve dp id for interface {} to handle router {} "
1165                     + "association model", interfaceName, routerName);
1166             return;
1167         }
1168
1169         LOG.debug("addToDpnRoutersMap : Adding the DPN {} and router {} for the Interface {} in the ODL-L3VPN : "
1170                 + "DPNRouters map", dpId, routerName, interfaceName);
1171         InstanceIdentifier<DpnRoutersList> dpnRoutersListIdentifier = getDpnRoutersId(dpId);
1172
1173         Optional<DpnRoutersList> optionalDpnRoutersList = operTx.read(dpnRoutersListIdentifier).get();
1174
1175         if (optionalDpnRoutersList.isPresent()) {
1176             RoutersList routersList = new RoutersListBuilder().withKey(new RoutersListKey(routerName))
1177                     .setRouter(routerName).build();
1178             List<RoutersList> routersListFromDs = optionalDpnRoutersList.get().nonnullRoutersList();
1179             if (!routersListFromDs.contains(routersList)) {
1180                 LOG.debug("addToDpnRoutersMap : Router {} not present for the DPN {}"
1181                         + " in the ODL-L3VPN : DPNRouters map", routerName, dpId);
1182                 operTx.merge(dpnRoutersListIdentifier
1183                         .child(RoutersList.class, new RoutersListKey(routerName)), routersList, CREATE_MISSING_PARENTS);
1184             } else {
1185                 LOG.debug("addToDpnRoutersMap : Router {} already mapped to the DPN {} in the ODL-L3VPN : "
1186                         + "DPNRouters map", routerName, dpId);
1187             }
1188         } else {
1189             LOG.debug("addToDpnRoutersMap : Building new DPNRoutersList for the Router {} present in the DPN {} "
1190                     + "ODL-L3VPN : DPNRouters map", routerName, dpId);
1191             DpnRoutersListBuilder dpnRoutersListBuilder = new DpnRoutersListBuilder();
1192             dpnRoutersListBuilder.setDpnId(dpId);
1193             RoutersListBuilder routersListBuilder = new RoutersListBuilder();
1194             routersListBuilder.setRouter(routerName);
1195             dpnRoutersListBuilder.setRoutersList(Collections.singletonList(routersListBuilder.build()));
1196             operTx.merge(getDpnRoutersId(dpId), dpnRoutersListBuilder.build(), CREATE_MISSING_PARENTS);
1197         }
1198     }
1199
1200     public static void removeFromNeutronRouterDpnsMap(String routerName, BigInteger dpId,
1201         TypedReadWriteTransaction<Operational> operTx) throws ExecutionException, InterruptedException {
1202         if (dpId.equals(BigInteger.ZERO)) {
1203             LOG.warn("removeFromNeutronRouterDpnsMap : DPN ID is invalid for the router {} ", routerName);
1204             return;
1205         }
1206
1207         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1208         Optional<DpnVpninterfacesList> optionalRouterDpnList = operTx.read(routerDpnListIdentifier).get();
1209         if (optionalRouterDpnList.isPresent()) {
1210             LOG.debug("removeFromNeutronRouterDpnsMap : Removing the dpn-vpninterfaces-list from the "
1211                     + "odl-l3vpn:neutron-router-dpns model for the router {}", routerName);
1212             operTx.delete(routerDpnListIdentifier);
1213         } else {
1214             LOG.debug("removeFromNeutronRouterDpnsMap : dpn-vpninterfaces-list does not exist in the "
1215                     + "odl-l3vpn:neutron-router-dpns model for the router {}", routerName);
1216         }
1217     }
1218
1219     public static void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,
1220          BigInteger dpId, @Nonnull TypedReadWriteTransaction<Operational> operTx) {
1221         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1222         Optional<DpnVpninterfacesList> optionalRouterDpnList;
1223         try {
1224             optionalRouterDpnList = operTx.read(routerDpnListIdentifier).get();
1225         } catch (InterruptedException | ExecutionException e) {
1226             LOG.error("Error reading the router DPN list for {}", routerDpnListIdentifier, e);
1227             optionalRouterDpnList = Optional.absent();
1228         }
1229         if (optionalRouterDpnList.isPresent()) {
1230             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns
1231                     .router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces> routerInterfaces =
1232                     optionalRouterDpnList.get().getRouterInterfaces();
1233             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn
1234                     .list.dpn.vpninterfaces.list.RouterInterfaces routerInterface =
1235                     new RouterInterfacesBuilder().withKey(new RouterInterfacesKey(vpnInterfaceName))
1236                             .setInterface(vpnInterfaceName).build();
1237
1238             if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1239                 if (routerInterfaces.isEmpty()) {
1240                     operTx.delete(routerDpnListIdentifier);
1241                 } else {
1242                     operTx.delete(routerDpnListIdentifier.child(
1243                             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router
1244                                     .dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
1245                             new RouterInterfacesKey(vpnInterfaceName)));
1246                 }
1247             }
1248         }
1249     }
1250
1251     public static void removeFromDpnRoutersMap(DataBroker broker, String routerName, String vpnInterfaceName,
1252         BigInteger curDpnId, OdlInterfaceRpcService ifaceMgrRpcService, TypedReadWriteTransaction<Operational> operTx)
1253         throws ExecutionException, InterruptedException {
1254         /*
1255             1) Get the DpnRoutersList for the DPN.
1256             2) Get the RoutersList identifier for the DPN and router.
1257             3) Get the VPN interfaces for the router (routerList) through which it is connected to the DPN.
1258             4) If the removed VPN interface is the only interface through which the router is connected to the DPN,
1259              then remove RouterList.
1260          */
1261
1262         LOG.debug("removeFromDpnRoutersMap() : Removing the DPN {} and router {} for the Interface {}"
1263             + " in the ODL-L3VPN : DPNRouters map", curDpnId, routerName, vpnInterfaceName);
1264
1265         //Get the dpn-routers-list instance for the current DPN.
1266         InstanceIdentifier<DpnRoutersList> dpnRoutersListIdentifier = getDpnRoutersId(curDpnId);
1267         Optional<DpnRoutersList> dpnRoutersListData = operTx.read(dpnRoutersListIdentifier).get();
1268
1269         if (dpnRoutersListData == null || !dpnRoutersListData.isPresent()) {
1270             LOG.error("removeFromDpnRoutersMap : dpn-routers-list is not present for DPN {} "
1271                     + "in the ODL-L3VPN:dpn-routers model", curDpnId);
1272             return;
1273         }
1274
1275         //Get the routers-list instance for the router on the current DPN only
1276         InstanceIdentifier<RoutersList> routersListIdentifier = getRoutersList(curDpnId, routerName);
1277         Optional<RoutersList> routersListData = operTx.read(routersListIdentifier).get();
1278
1279         if (routersListData == null || !routersListData.isPresent()) {
1280             LOG.error("removeFromDpnRoutersMap : routers-list is not present for the DPN {} "
1281                     + "in the ODL-L3VPN:dpn-routers model",
1282                 curDpnId);
1283             return;
1284         }
1285
1286         LOG.debug("removeFromDpnRoutersMap : Get the interfaces for the router {} "
1287                 + "from the NeutronVPN - router-interfaces-map", routerName);
1288         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router
1289             .interfaces.map.RouterInterfaces> routerInterfacesId = getRoutersInterfacesIdentifier(routerName);
1290         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map
1291                 .RouterInterfaces> routerInterfacesData =
1292                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1293                         LogicalDatastoreType.CONFIGURATION, routerInterfacesId);
1294
1295         if (routerInterfacesData == null || !routerInterfacesData.isPresent()) {
1296             LOG.debug("removeFromDpnRoutersMap : Unable to get the routers list for the DPN {}. Possibly all subnets "
1297                     + "removed from router {} OR Router {} has been deleted. Hence DPN router model WILL be cleared ",
1298                 curDpnId, routerName, routerName);
1299             operTx.delete(routersListIdentifier);
1300             return;
1301         }
1302
1303         //Get the VM interfaces for the router on the current DPN only.
1304         List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces
1305             .map.router.interfaces.Interfaces> vmInterfaces = routerInterfacesData.get().getInterfaces();
1306         if (vmInterfaces == null) {
1307             LOG.debug("removeFromDpnRoutersMap : VM interfaces are not present for the router {} in the "
1308                 + "NeutronVPN - router-interfaces-map", routerName);
1309             return;
1310         }
1311
1312         // If the removed VPN interface is the only interface through which the router is connected to the DPN,
1313         // then remove RouterList.
1314         for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map
1315                  .router.interfaces.Interfaces vmInterface : vmInterfaces) {
1316             String vmInterfaceName = vmInterface.getInterfaceId();
1317             BigInteger vmDpnId = getDpnForInterface(ifaceMgrRpcService, vmInterfaceName);
1318             if (vmDpnId.equals(BigInteger.ZERO) || !vmDpnId.equals(curDpnId)) {
1319                 LOG.debug("removeFromDpnRoutersMap : DPN ID {} for the removed interface {} is not the same as that of "
1320                         + "the DPN ID {} for the checked interface {}",
1321                     curDpnId, vpnInterfaceName, vmDpnId, vmInterfaceName);
1322                 continue;
1323             }
1324             if (!vmInterfaceName.equalsIgnoreCase(vpnInterfaceName)) {
1325                 LOG.info("removeFromDpnRoutersMap : Router {} is present in the DPN {} through the other interface {} "
1326                     + "Hence DPN router model WOULD NOT be cleared", routerName, curDpnId, vmInterfaceName);
1327                 return;
1328             }
1329         }
1330         LOG.debug("removeFromDpnRoutersMap : Router {} is present in the DPN {} only through the interface {} "
1331             + "Hence DPN router model WILL be cleared. Possibly last VM for the router "
1332             + "deleted in the DPN", routerName, curDpnId, vpnInterfaceName);
1333         operTx.delete(routersListIdentifier);
1334     }
1335
1336     private static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
1337         .rev150602.router.interfaces.map.RouterInterfaces> getRoutersInterfacesIdentifier(String routerName) {
1338         return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn
1339             .rev150602.RouterInterfacesMap.class)
1340             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router
1341                     .interfaces.map.RouterInterfaces.class,
1342                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router
1343                     .interfaces.map.RouterInterfacesKey(new Uuid(routerName))).build();
1344     }
1345
1346     private static InstanceIdentifier<RoutersList> getRoutersList(BigInteger dpnId, String routerName) {
1347         return InstanceIdentifier.builder(DpnRouters.class)
1348             .child(DpnRoutersList.class, new DpnRoutersListKey(dpnId))
1349             .child(RoutersList.class, new RoutersListKey(routerName)).build();
1350     }
1351
1352     public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
1353         BigInteger nodeId = BigInteger.ZERO;
1354         try {
1355             GetDpidFromInterfaceInput
1356                 dpIdInput =
1357                 new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
1358             Future<RpcResult<GetDpidFromInterfaceOutput>>
1359                 dpIdOutput =
1360                 interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
1361             RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
1362             if (dpIdResult.isSuccessful()) {
1363                 nodeId = dpIdResult.getResult().getDpid();
1364             } else {
1365                 LOG.debug("getDpnForInterface : Could not retrieve DPN Id for interface {}", ifName);
1366             }
1367         } catch (NullPointerException | InterruptedException | ExecutionException e) {
1368             LOG.error("getDpnForInterface : Exception when getting dpn for interface {}", ifName, e);
1369         }
1370         return nodeId;
1371     }
1372
1373     @Nonnull
1374     public static List<ActionInfo> getEgressActionsForInterface(OdlInterfaceRpcService odlInterfaceRpcService,
1375                                                                 ItmRpcService itmRpcService,
1376                                                                 IInterfaceManager interfaceManager, String ifName,
1377                                                                 Long tunnelKey, boolean internalTunnelInterface) {
1378         return getEgressActionsForInterface(odlInterfaceRpcService, itmRpcService, interfaceManager,
1379                 ifName, tunnelKey, 0, internalTunnelInterface);
1380     }
1381
1382     @Nonnull
1383     public static List<ActionInfo> getEgressActionsForInterface(OdlInterfaceRpcService odlInterfaceRpcService,
1384                                                                 ItmRpcService itmRpcService,
1385                                                                 IInterfaceManager interfaceManager,
1386                                                                 String ifName, @Nullable Long tunnelKey, int pos,
1387                                                                 boolean internalTunnelInterface) {
1388         LOG.debug("getEgressActionsForInterface : called for interface {}", ifName);
1389         GetEgressActionsForInterfaceInputBuilder egressActionsIfmBuilder =
1390                 new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName);
1391         GetEgressActionsForTunnelInputBuilder egressActionsItmBuilder =
1392                 new GetEgressActionsForTunnelInputBuilder().setIntfName(ifName);
1393         if (tunnelKey != null) {
1394             egressActionsIfmBuilder.setTunnelKey(tunnelKey);
1395             egressActionsItmBuilder.setTunnelKey(tunnelKey);
1396         } //init builders, ITM/IFM rpc can be called based on type of interface
1397
1398         try {
1399             List<Action> actions = emptyList();
1400             if (interfaceManager.isItmDirectTunnelsEnabled() && internalTunnelInterface) {
1401                 RpcResult<GetEgressActionsForTunnelOutput> rpcResult =
1402                         itmRpcService.getEgressActionsForTunnel(egressActionsItmBuilder.build()).get();
1403                 if (!rpcResult.isSuccessful()) {
1404                     LOG.error("getEgressActionsForTunnels : RPC Call to Get egress actions for Tunnels {} "
1405                             + "returned with Errors {}", ifName, rpcResult.getErrors());
1406                 } else {
1407                     actions = rpcResult.getResult().nonnullAction();
1408                 }
1409             } else {
1410                 RpcResult<GetEgressActionsForInterfaceOutput> rpcResult =
1411                         odlInterfaceRpcService.getEgressActionsForInterface(egressActionsIfmBuilder.build()).get();
1412                 if (!rpcResult.isSuccessful()) {
1413                     LOG.error("getEgressActionsForInterface : RPC Call to Get egress actions for interface {} "
1414                             + "returned with Errors {}", ifName, rpcResult.getErrors());
1415                 } else {
1416                     actions = rpcResult.getResult().nonnullAction();
1417                 }
1418             }
1419             List<ActionInfo> listActionInfo = new ArrayList<>();
1420             for (Action action : actions) {
1421                 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action
1422                     actionClass = action.getAction();
1423                 if (actionClass instanceof OutputActionCase) {
1424                     listActionInfo.add(new ActionOutput(pos++,
1425                         ((OutputActionCase) actionClass).getOutputAction().getOutputNodeConnector()));
1426                 } else if (actionClass instanceof PushVlanActionCase) {
1427                     listActionInfo.add(new ActionPushVlan(pos++));
1428                 } else if (actionClass instanceof SetFieldCase) {
1429                     if (((SetFieldCase) actionClass).getSetField().getVlanMatch() != null) {
1430                         int vlanVid = ((SetFieldCase) actionClass).getSetField().getVlanMatch().getVlanId()
1431                             .getVlanId().getValue();
1432                         listActionInfo.add(new ActionSetFieldVlanVid(pos++, vlanVid));
1433                     }
1434                 } else if (actionClass instanceof NxActionResubmitRpcAddGroupCase) {
1435                     Short tableId = ((NxActionResubmitRpcAddGroupCase) actionClass).getNxResubmit().getTable();
1436                     listActionInfo.add(new ActionNxResubmit(pos++, tableId));
1437                 } else if (actionClass instanceof NxActionRegLoadNodesNodeTableFlowApplyActionsCase) {
1438                     NxRegLoad nxRegLoad =
1439                         ((NxActionRegLoadNodesNodeTableFlowApplyActionsCase) actionClass).getNxRegLoad();
1440                     listActionInfo.add(new ActionRegLoad(pos++, NxmNxReg6.class, nxRegLoad.getDst().getStart(),
1441                         nxRegLoad.getDst().getEnd(), nxRegLoad.getValue().longValue()));
1442                 }
1443             }
1444             return listActionInfo;
1445         } catch (InterruptedException | ExecutionException e) {
1446             LOG.error("Exception when egress actions for interface {}", ifName, e);
1447         }
1448         LOG.error("Error when getting egress actions for interface {}", ifName);
1449         return emptyList();
1450     }
1451
1452     @Nullable
1453     public static Port getNeutronPortForRouterGetewayIp(DataBroker broker, IpAddress targetIP) {
1454         return getNeutronPortForIp(broker, targetIP, NeutronConstants.DEVICE_OWNER_GATEWAY_INF);
1455     }
1456
1457     @Nonnull
1458     public static List<Port> getNeutronPorts(DataBroker broker) {
1459         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports>
1460             portsIdentifier = InstanceIdentifier.create(Neutron.class)
1461             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports.class);
1462         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports>
1463                 portsOptional =
1464                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1465                         LogicalDatastoreType.CONFIGURATION, portsIdentifier);
1466
1467         if (!portsOptional.isPresent() || portsOptional.get().getPort() == null) {
1468             LOG.error("getNeutronPorts : No neutron ports found");
1469             return emptyList();
1470         }
1471
1472         return portsOptional.get().getPort();
1473     }
1474
1475     @Nullable
1476     public static Port getNeutronPortForIp(DataBroker broker, IpAddress targetIP, String deviceType) {
1477         List<Port> ports = getNeutronPorts(
1478             broker);
1479
1480         for (Port port : ports) {
1481             if (deviceType.equals(port.getDeviceOwner()) && port.getFixedIps() != null) {
1482                 for (FixedIps ip : port.getFixedIps()) {
1483                     if (Objects.equals(ip.getIpAddress(), targetIP)) {
1484                         return port;
1485                     }
1486                 }
1487             }
1488         }
1489         LOG.error("getNeutronPortForIp : Neutron Port missing for IP:{} DeviceType:{}", targetIP, deviceType);
1490         return null;
1491     }
1492
1493     @Nullable
1494     public static Uuid getSubnetIdForFloatingIp(Port port, IpAddress targetIP) {
1495         if (port == null) {
1496             LOG.error("getSubnetIdForFloatingIp : port is null");
1497             return null;
1498         }
1499         for (FixedIps ip : port.nonnullFixedIps()) {
1500             if (Objects.equals(ip.getIpAddress(), targetIP)) {
1501                 return ip.getSubnetId();
1502             }
1503         }
1504         LOG.error("getSubnetIdForFloatingIp : No Fixed IP configured for targetIP:{}", targetIP);
1505         return null;
1506     }
1507
1508     @Nullable
1509     public static Subnetmap getSubnetMap(DataBroker broker, Uuid subnetId) {
1510         InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier.builder(Subnetmaps.class)
1511             .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
1512         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1513                 LogicalDatastoreType.CONFIGURATION, subnetmapId).orNull();
1514     }
1515
1516     @Nonnull
1517     public static List<Uuid> getSubnetIdsFromNetworkId(DataBroker broker, Uuid networkId) {
1518         InstanceIdentifier<NetworkMap> id = InstanceIdentifier.builder(NetworkMaps.class)
1519             .child(NetworkMap.class, new NetworkMapKey(networkId)).build();
1520         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1521                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(NetworkMap::getSubnetIdList).orElse(
1522                 emptyList());
1523     }
1524
1525     @Nullable
1526     public static String getSubnetGwMac(DataBroker broker, Uuid subnetId, String vpnName) {
1527         if (subnetId == null) {
1528             LOG.error("getSubnetGwMac : subnetID is null");
1529             return null;
1530         }
1531
1532         InstanceIdentifier<Subnet> subnetInst = InstanceIdentifier.create(Neutron.class).child(Subnets.class)
1533             .child(Subnet.class, new SubnetKey(subnetId));
1534         Optional<Subnet> subnetOpt =
1535                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1536                         LogicalDatastoreType.CONFIGURATION, subnetInst);
1537         if (!subnetOpt.isPresent()) {
1538             LOG.error("getSubnetGwMac : unable to obtain Subnet for id : {}", subnetId);
1539             return null;
1540         }
1541
1542         IpAddress gatewayIp = subnetOpt.get().getGatewayIp();
1543         if (gatewayIp == null) {
1544             LOG.warn("getSubnetGwMac : No GW ip found for subnet {}", subnetId.getValue());
1545             return null;
1546         }
1547
1548         if (null != gatewayIp.getIpv6Address()) {
1549             return null;
1550         }
1551
1552         InstanceIdentifier<VpnPortipToPort> portIpInst = InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
1553             .child(VpnPortipToPort.class, new VpnPortipToPortKey(gatewayIp.getIpv4Address().getValue(), vpnName))
1554             .build();
1555         Optional<VpnPortipToPort> portIpToPortOpt =
1556                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1557                         LogicalDatastoreType.CONFIGURATION, portIpInst);
1558         if (portIpToPortOpt.isPresent()) {
1559             return portIpToPortOpt.get().getMacAddress();
1560         }
1561
1562         InstanceIdentifier<LearntVpnVipToPort> learntIpInst = InstanceIdentifier.builder(LearntVpnVipToPortData.class)
1563             .child(LearntVpnVipToPort.class, new LearntVpnVipToPortKey(gatewayIp.getIpv4Address().getValue(), vpnName))
1564             .build();
1565         Optional<LearntVpnVipToPort> learntIpToPortOpt =
1566                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1567                         LogicalDatastoreType.OPERATIONAL, learntIpInst);
1568         if (learntIpToPortOpt.isPresent()) {
1569             return learntIpToPortOpt.get().getMacAddress();
1570         }
1571
1572         LOG.info("getSubnetGwMac : No resolution was found to GW ip {} in subnet {}", gatewayIp, subnetId.getValue());
1573         return null;
1574     }
1575
1576     public static boolean isIPv6Subnet(String prefix) {
1577         return IpPrefixBuilder.getDefaultInstance(prefix).getIpv6Prefix() != null;
1578     }
1579
1580     static InstanceIdentifier<DpnRoutersList> getDpnRoutersId(BigInteger dpnId) {
1581         return InstanceIdentifier.builder(DpnRouters.class)
1582             .child(DpnRoutersList.class, new DpnRoutersListKey(dpnId)).build();
1583     }
1584
1585     static InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1586         return InstanceIdentifier.builder(NeutronRouterDpns.class)
1587             .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1588             .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1589     }
1590
1591     static InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1592         return InstanceIdentifier.builder(NeutronRouterDpns.class)
1593             .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1594     }
1595
1596     @Nullable
1597     protected static String getFloatingIpPortMacFromFloatingIpId(DataBroker broker, Uuid floatingIpId) {
1598         InstanceIdentifier<FloatingIpIdToPortMapping> id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
1599         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1600                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
1601                 FloatingIpIdToPortMapping::getFloatingIpPortMacAddress).orElse(null);
1602     }
1603
1604     @Nullable
1605     protected static String getFloatingIpPortMacFromFloatingIpId(TypedReadTransaction<Configuration> confTx,
1606         Uuid floatingIpId) {
1607         try {
1608             return confTx.read(buildfloatingIpIdToPortMappingIdentifier(floatingIpId)).get().toJavaUtil().map(
1609                 FloatingIpIdToPortMapping::getFloatingIpPortMacAddress).orElse(null);
1610         } catch (InterruptedException | ExecutionException e) {
1611             LOG.error("Error reading the floating IP port MAC for {}", floatingIpId, e);
1612             return null;
1613         }
1614     }
1615
1616     @Nullable
1617     protected static Uuid getFloatingIpPortSubnetIdFromFloatingIpId(DataBroker broker, Uuid floatingIpId) {
1618         InstanceIdentifier<FloatingIpIdToPortMapping> id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
1619         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1620                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
1621                 FloatingIpIdToPortMapping::getFloatingIpPortSubnetId).orElse(null);
1622     }
1623
1624     @Nullable
1625     protected static Uuid getFloatingIpPortSubnetIdFromFloatingIpId(TypedReadTransaction<Configuration> confTx,
1626         Uuid floatingIpId) {
1627         try {
1628             return confTx.read(buildfloatingIpIdToPortMappingIdentifier(floatingIpId)).get().toJavaUtil().map(
1629                 FloatingIpIdToPortMapping::getFloatingIpPortSubnetId).orElse(null);
1630         } catch (InterruptedException | ExecutionException e) {
1631             LOG.error("Error reading the floating IP port subnet for {}", floatingIpId, e);
1632             return null;
1633         }
1634     }
1635
1636     static InstanceIdentifier<FloatingIpIdToPortMapping> buildfloatingIpIdToPortMappingIdentifier(Uuid floatingIpId) {
1637         return InstanceIdentifier.builder(FloatingIpPortInfo.class).child(FloatingIpIdToPortMapping.class, new
1638             FloatingIpIdToPortMappingKey(floatingIpId)).build();
1639     }
1640
1641     @Nullable
1642     static Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
1643         InstanceIdentifier<Interface> ifStateId =
1644             buildStateInterfaceId(interfaceName);
1645         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1646                 LogicalDatastoreType.OPERATIONAL, ifStateId).orNull();
1647     }
1648
1649     static InstanceIdentifier<Interface> buildStateInterfaceId(String interfaceName) {
1650         InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
1651             InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
1652                 .interfaces.rev140508.InterfacesState.class)
1653                 .child(Interface.class,
1654                     new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
1655                         .interfaces.state.InterfaceKey(interfaceName));
1656         return idBuilder.build();
1657     }
1658
1659     @Nullable
1660     public static Routers getRoutersFromConfigDS(DataBroker dataBroker, String routerName) {
1661         InstanceIdentifier<Routers> routerIdentifier = NatUtil.buildRouterIdentifier(routerName);
1662         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1663                 LogicalDatastoreType.CONFIGURATION, routerIdentifier).orNull();
1664     }
1665
1666     @Nullable
1667     public static Routers getRoutersFromConfigDS(TypedReadTransaction<Configuration> confTx, String routerName) {
1668         try {
1669             return confTx.read(NatUtil.buildRouterIdentifier(routerName)).get().orNull();
1670         } catch (InterruptedException | ExecutionException e) {
1671             LOG.error("Error reading router {}", routerName, e);
1672             return null;
1673         }
1674     }
1675
1676     static void createRouterIdsConfigDS(DataBroker dataBroker, long routerId, String routerName) {
1677         if (routerId == NatConstants.INVALID_ID) {
1678             LOG.error("createRouterIdsConfigDS : invalid routerId for routerName {}", routerName);
1679             return;
1680         }
1681         RouterIds rtrs = new RouterIdsBuilder().withKey(new RouterIdsKey(routerId))
1682             .setRouterId(routerId).setRouterName(routerName).build();
1683         MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, buildRouterIdentifier(routerId), rtrs);
1684     }
1685
1686     @Nullable
1687     static FlowEntity buildDefaultNATFlowEntityForExternalSubnet(BigInteger dpId, long vpnId, String subnetId,
1688             IdManagerService idManager) {
1689         InetAddress defaultIP = null;
1690         try {
1691             defaultIP = InetAddress.getByName("0.0.0.0");
1692         } catch (UnknownHostException e) {
1693             LOG.error("buildDefaultNATFlowEntityForExternalSubnet : Failed to build FIB Table Flow for "
1694                     + "Default Route to NAT.", e);
1695             return null;
1696         }
1697
1698         List<MatchInfo> matches = new ArrayList<>();
1699         matches.add(MatchEthernetType.IPV4);
1700         //add match for vrfid
1701         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
1702
1703         List<InstructionInfo> instructions = new ArrayList<>();
1704         List<ActionInfo> actionsInfo = new ArrayList<>();
1705         long groupId = createGroupId(NatUtil.getGroupIdKey(subnetId), idManager);
1706         actionsInfo.add(new ActionGroup(groupId));
1707         String flowRef = getFlowRef(dpId, NwConstants.L3_FIB_TABLE, defaultIP, vpnId);
1708         instructions.add(new InstructionApplyActions(actionsInfo));
1709         return MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_FIB_TABLE, flowRef,
1710                 NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
1711                 NwConstants.COOKIE_DNAT_TABLE, matches, instructions);
1712     }
1713
1714     @Nullable
1715     static String getExtGwMacAddFromRouterId(DataBroker broker, long routerId) {
1716         String routerName = getRouterName(broker, routerId);
1717         if (routerName == null) {
1718             LOG.error("getExtGwMacAddFromRouterId : empty routerName received");
1719             return null;
1720         }
1721         return getExtGwMacAddFromRouterName(broker, routerName);
1722     }
1723
1724     @Nullable
1725     static String getExtGwMacAddFromRouterName(DataBroker broker, String routerName) {
1726         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerName);
1727         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1728                 LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(Routers::getExtGwMacAddress).orElse(null);
1729     }
1730
1731     @Nullable
1732     static String getExtGwMacAddFromRouterName(TypedReadTransaction<Configuration> tx, String routerName) {
1733         try {
1734             return tx.read(buildRouterIdentifier(routerName)).get().toJavaUtil().map(
1735                 Routers::getExtGwMacAddress).orElse(null);
1736         } catch (InterruptedException | ExecutionException e) {
1737             LOG.error("Error retrieving external gateway MAC address for router {}", routerName, e);
1738             return null;
1739         }
1740     }
1741
1742     static InstanceIdentifier<Router> buildNeutronRouterIdentifier(Uuid routerUuid) {
1743         InstanceIdentifier<Router> routerInstanceIdentifier = InstanceIdentifier.create(Neutron.class)
1744              .child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers.class)
1745              .child(Router.class, new RouterKey(routerUuid));
1746         return routerInstanceIdentifier;
1747     }
1748
1749     @Nullable
1750     public static String getNeutronRouterNamebyUuid(DataBroker broker, Uuid routerUuid) {
1751         InstanceIdentifier<Router> neutronRouterIdentifier = NatUtil.buildNeutronRouterIdentifier(routerUuid);
1752         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1753                 LogicalDatastoreType.CONFIGURATION, neutronRouterIdentifier).toJavaUtil().map(Router::getName).orElse(
1754                 null);
1755     }
1756
1757     @Nonnull
1758     public static List<Ports> getFloatingIpPortsForRouter(DataBroker broker, Uuid routerUuid) {
1759         InstanceIdentifier<RouterPorts> routerPortsIdentifier = getRouterPortsId(routerUuid.getValue());
1760         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1761                 LogicalDatastoreType.CONFIGURATION,
1762                 routerPortsIdentifier).toJavaUtil().map(RouterPorts::getPorts).orElse(emptyList());
1763     }
1764
1765     @Nonnull
1766     public static List<Uuid> getRouterUuIdsForVpn(DataBroker broker, Uuid vpnUuid) {
1767         InstanceIdentifier<ExternalNetworks> externalNwIdentifier = InstanceIdentifier.create(ExternalNetworks.class);
1768         Optional<ExternalNetworks> externalNwData =
1769                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1770                         LogicalDatastoreType.CONFIGURATION, externalNwIdentifier);
1771         if (externalNwData.isPresent()) {
1772             for (Networks externalNw : externalNwData.get().nonnullNetworks()) {
1773                 if (externalNw.getVpnid() != null && externalNw.getVpnid().equals(vpnUuid)) {
1774                     @Nullable List<Uuid> routerIds = externalNw.getRouterIds();
1775                     return routerIds != null ? routerIds : emptyList();
1776                 }
1777             }
1778         }
1779         return emptyList();
1780     }
1781
1782     public static boolean isIpInSubnet(String ipAddress, String start, String end) {
1783
1784         try {
1785             long ipLo = ipToLong(InetAddress.getByName(start));
1786             long ipHi = ipToLong(InetAddress.getByName(end));
1787             long ipToTest = ipToLong(InetAddress.getByName(ipAddress));
1788             return ipToTest >= ipLo && ipToTest <= ipHi;
1789         } catch (UnknownHostException e) {
1790             LOG.error("isIpInSubnet : failed for IP {}", ipAddress, e);
1791             return false;
1792         }
1793     }
1794
1795     @Nonnull
1796     public static Collection<Uuid> getExternalSubnetIdsFromExternalIps(@Nullable List<ExternalIps> externalIps) {
1797         if (externalIps == null) {
1798             return Collections.emptySet();
1799         }
1800
1801         return externalIps.stream().map(ExternalIps::getSubnetId).collect(Collectors.toSet());
1802     }
1803
1804     @Nonnull
1805     public static Collection<Uuid> getExternalSubnetIdsForRouter(DataBroker dataBroker, @Nullable String routerName) {
1806         if (routerName == null) {
1807             LOG.error("getExternalSubnetIdsForRouter : empty routerName received");
1808             return Collections.emptySet();
1809         }
1810
1811         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerName);
1812         Optional<Routers> routerData =
1813                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1814                         LogicalDatastoreType.CONFIGURATION, id);
1815         if (routerData.isPresent()) {
1816             return NatUtil.getExternalSubnetIdsFromExternalIps(routerData.get().getExternalIps());
1817         } else {
1818             LOG.warn("getExternalSubnetIdsForRouter : No external router data for router {}", routerName);
1819             return Collections.emptySet();
1820         }
1821     }
1822
1823     @Nonnull
1824     protected static Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
1825         .subnets.Subnets> getOptionalExternalSubnets(DataBroker dataBroker, Uuid subnetId) {
1826         if (subnetId == null) {
1827             LOG.warn("getOptionalExternalSubnets : subnetId is null");
1828             return Optional.absent();
1829         }
1830
1831         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice
1832             .rev160111.external.subnets.Subnets> subnetsIdentifier =
1833                 InstanceIdentifier.builder(ExternalSubnets.class)
1834                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice
1835                         .rev160111.external.subnets.Subnets.class, new SubnetsKey(subnetId)).build();
1836         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
1837                 LogicalDatastoreType.CONFIGURATION, subnetsIdentifier);
1838     }
1839
1840     @Nonnull
1841     protected static Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
1842         .subnets.Subnets> getOptionalExternalSubnets(TypedReadTransaction<Configuration> tx, Uuid subnetId) {
1843         if (subnetId == null) {
1844             LOG.warn("getOptionalExternalSubnets : subnetId is null");
1845             return Optional.absent();
1846         }
1847
1848         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice
1849             .rev160111.external.subnets.Subnets> subnetsIdentifier =
1850             InstanceIdentifier.builder(ExternalSubnets.class)
1851                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice
1852                     .rev160111.external.subnets.Subnets.class, new SubnetsKey(subnetId)).build();
1853         try {
1854             return tx.read(subnetsIdentifier).get();
1855         } catch (InterruptedException | ExecutionException e) {
1856             LOG.error("Error retrieving external subnets on {}", subnetId, e);
1857             return Optional.absent();
1858         }
1859     }
1860
1861     protected static long getExternalSubnetVpnId(DataBroker dataBroker, Uuid subnetId) {
1862         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
1863             .subnets.Subnets> optionalExternalSubnets = NatUtil.getOptionalExternalSubnets(dataBroker,
1864                    subnetId);
1865         if (optionalExternalSubnets.isPresent()) {
1866             return NatUtil.getVpnId(dataBroker, subnetId.getValue());
1867         }
1868
1869         return NatConstants.INVALID_ID;
1870     }
1871
1872     protected static long getExternalSubnetVpnId(TypedReadTransaction<Configuration> tx, Uuid subnetId) {
1873         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
1874             .subnets.Subnets> optionalExternalSubnets = NatUtil.getOptionalExternalSubnets(tx,
1875             subnetId);
1876         if (optionalExternalSubnets.isPresent()) {
1877             return NatUtil.getVpnId(tx, subnetId.getValue());
1878         }
1879
1880         return NatConstants.INVALID_ID;
1881     }
1882
1883     protected static long getExternalSubnetVpnIdForRouterExternalIp(DataBroker dataBroker, String externalIpAddress,
1884             Routers router) {
1885         Uuid externalSubnetId = NatUtil.getExternalSubnetForRouterExternalIp(externalIpAddress, router);
1886         if (externalSubnetId != null) {
1887             return NatUtil.getExternalSubnetVpnId(dataBroker,externalSubnetId);
1888         }
1889
1890         return NatConstants.INVALID_ID;
1891     }
1892
1893     @Nullable
1894     protected static Uuid getExternalSubnetForRouterExternalIp(String externalIpAddress, Routers router) {
1895         externalIpAddress = validateAndAddNetworkMask(externalIpAddress);
1896         for (ExternalIps extIp : router.nonnullExternalIps()) {
1897             String extIpString = validateAndAddNetworkMask(extIp.getIpAddress());
1898             if (extIpString.equals(externalIpAddress)) {
1899                 return extIp.getSubnetId();
1900             }
1901         }
1902         LOG.warn("getExternalSubnetForRouterExternalIp : Missing External Subnet for Ip:{}", externalIpAddress);
1903         return null;
1904     }
1905
1906     private static long ipToLong(InetAddress ip) {
1907         byte[] octets = ip.getAddress();
1908         long result = 0;
1909         for (byte octet : octets) {
1910             result <<= 8;
1911             result |= octet & 0xff;
1912         }
1913         return result;
1914     }
1915
1916     @Nonnull
1917     static List<String> getIpsListFromExternalIps(@Nullable List<ExternalIps> externalIps) {
1918         if (externalIps == null) {
1919             return emptyList();
1920         }
1921
1922         return externalIps.stream().map(ExternalIps::getIpAddress).collect(Collectors.toList());
1923     }
1924
1925     // elan-instances config container
1926     @Nullable
1927     public static ElanInstance getElanInstanceByName(String elanInstanceName, DataBroker broker) {
1928         InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
1929         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
1930                 LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orNull();
1931     }
1932
1933     @Nullable
1934     public static ElanInstance getElanInstanceByName(TypedReadTransaction<Configuration> tx, String elanInstanceName) {
1935         try {
1936             return tx.read(getElanInstanceConfigurationDataPath(elanInstanceName)).get().orNull();
1937         } catch (InterruptedException | ExecutionException e) {
1938             LOG.error("Error retrieving ELAN instance by name {}", elanInstanceName, e);
1939             return null;
1940         }
1941     }
1942
1943     public static InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
1944         return InstanceIdentifier.builder(ElanInstances.class)
1945                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
1946     }
1947
1948     public static long getTunnelIdForNonNaptToNaptFlow(DataBroker dataBroker, NatOverVxlanUtil natOverVxlanUtil,
1949                                                        IElanService elanManager, IdManagerService idManager,
1950                                                        long routerId, String routerName) {
1951         if (elanManager.isOpenStackVniSemanticsEnforced()) {
1952             // Router VNI will be set as tun_id if OpenStackSemantics is enabled
1953             return natOverVxlanUtil.getRouterVni(routerName, routerId).longValue();
1954         } else {
1955             return NatEvpnUtil.getTunnelIdForRouter(idManager, dataBroker, routerName, routerId);
1956         }
1957     }
1958
1959     public static void makePreDnatToSnatTableEntry(IMdsalApiManager mdsalManager, BigInteger naptDpnId,
1960             short tableId, TypedWriteTransaction<Configuration> confTx) {
1961         LOG.debug("makePreDnatToSnatTableEntry : Create Pre-DNAT table {} --> table {} flow on NAPT DpnId {} ",
1962                 NwConstants.PDNAT_TABLE, tableId, naptDpnId);
1963
1964         List<Instruction> preDnatToSnatInstructions = new ArrayList<>();
1965         preDnatToSnatInstructions.add(new InstructionGotoTable(tableId).buildInstruction(0));
1966         List<MatchInfo> matches = new ArrayList<>();
1967         matches.add(MatchEthernetType.IPV4);
1968         String flowRef = getFlowRefPreDnatToSnat(naptDpnId, NwConstants.PDNAT_TABLE, "PreDNATToSNAT");
1969         Flow preDnatToSnatTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.PDNAT_TABLE,flowRef,
1970                 5, flowRef, 0, 0,  NwConstants.COOKIE_DNAT_TABLE,
1971                 matches, preDnatToSnatInstructions);
1972
1973         mdsalManager.addFlow(confTx, naptDpnId, preDnatToSnatTableFlowEntity);
1974         LOG.debug("makePreDnatToSnatTableEntry : Successfully installed Pre-DNAT flow {} on NAPT DpnId {} ",
1975                 preDnatToSnatTableFlowEntity,  naptDpnId);
1976     }
1977
1978     public static void removePreDnatToSnatTableEntry(TypedReadWriteTransaction<Configuration> confTx,
1979             IMdsalApiManager mdsalManager, BigInteger naptDpnId) throws ExecutionException, InterruptedException {
1980         LOG.debug("removePreDnatToSnatTableEntry : Remove Pre-DNAT table {} --> table {} flow on NAPT DpnId {} ",
1981                 NwConstants.PDNAT_TABLE, NwConstants.INBOUND_NAPT_TABLE, naptDpnId);
1982         String flowRef = getFlowRefPreDnatToSnat(naptDpnId, NwConstants.PDNAT_TABLE, "PreDNATToSNAT");
1983         mdsalManager.removeFlow(confTx, naptDpnId, flowRef, NwConstants.PDNAT_TABLE);
1984         LOG.debug("removePreDnatToSnatTableEntry: Successfully removed Pre-DNAT flow {} on NAPT DpnId = {}",
1985                 flowRef, naptDpnId);
1986     }
1987
1988     private static String getFlowRefPreDnatToSnat(BigInteger dpnId, short tableId, String uniqueId) {
1989         return NatConstants.NAPT_FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId
1990                 + NwConstants.FLOWID_SEPARATOR + uniqueId;
1991     }
1992
1993     public static boolean isFloatingIpPresentForDpn(DataBroker dataBroker, BigInteger dpnId, String rd,
1994                                                     String vpnName, String externalIp,
1995                                                     Boolean isMoreThanOneFipCheckOnDpn) {
1996         InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
1997         Optional<VpnToDpnList> dpnInVpn = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
1998         if (dpnInVpn.isPresent()) {
1999             LOG.debug("isFloatingIpPresentForDpn : vpn-to-dpn-list is not empty for vpnName {}, dpn id {}, "
2000                     + "rd {} and floatingIp {}", vpnName, dpnId, rd, externalIp);
2001             try {
2002                 List<IpAddresses> ipAddressList = dpnInVpn.get().getIpAddresses();
2003                 if (ipAddressList != null && !ipAddressList.isEmpty()) {
2004                     int floatingIpPresentCount = 0;
2005                     for (IpAddresses ipAddress: ipAddressList) {
2006                         if (!Objects.equals(ipAddress.getIpAddress(), externalIp)
2007                                 && IpAddresses.IpAddressSource.FloatingIP.equals(ipAddress.getIpAddressSource())) {
2008                             floatingIpPresentCount++;
2009                             //Add tunnel table check
2010                             if (isMoreThanOneFipCheckOnDpn && floatingIpPresentCount > 1) {
2011                                 return true;
2012                             }
2013                             //Remove tunnel table check
2014                             if (!isMoreThanOneFipCheckOnDpn) {
2015                                 return true;
2016                             }
2017                         }
2018                     }
2019                 } else {
2020                     LOG.debug("isFloatingIpPresentForDpn : vpn-to-dpn-list does not contain any floating IP for DPN {}",
2021                            dpnId);
2022                     return false;
2023                 }
2024             } catch (NullPointerException e) {
2025                 LOG.error("isFloatingIpPresentForDpn: Exception occurred on getting external IP address from "
2026                         + "vpn-to-dpn-list on Dpn {}", dpnId, e);
2027                 return false;
2028             }
2029         }
2030         return false;
2031     }
2032
2033     private static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
2034         return InstanceIdentifier.builder(VpnInstanceOpData.class)
2035                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd))
2036                 .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
2037     }
2038
2039     @Nullable
2040     public static String getPrimaryRd(String vpnName, TypedReadTransaction<Configuration> tx)
2041         throws ExecutionException, InterruptedException {
2042         return tx.read(getVpnInstanceIdentifier(vpnName)).get().toJavaUtil().map(NatUtil::getPrimaryRd).orElse(null);
2043     }
2044
2045     public static String getPrimaryRd(DataBroker dataBroker, String vpnName) {
2046         InstanceIdentifier<VpnInstance> id  = getVpnInstanceIdentifier(vpnName);
2047         Optional<VpnInstance> vpnInstance =
2048                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
2049                         LogicalDatastoreType.CONFIGURATION, id);
2050         if (vpnInstance.isPresent()) {
2051             return getPrimaryRd(vpnInstance.get());
2052         }
2053         return vpnName;
2054     }
2055
2056     @Nullable
2057     public static String getPrimaryRd(@Nullable VpnInstance vpnInstance) {
2058         if (vpnInstance == null) {
2059             return null;
2060         }
2061         List<String> rds = getListOfRdsFromVpnInstance(vpnInstance);
2062         return rds.isEmpty() ? vpnInstance.getVpnInstanceName() : rds.get(0);
2063     }
2064
2065     public static InstanceIdentifier<VpnInstance> getVpnInstanceIdentifier(String vpnName) {
2066         return InstanceIdentifier.builder(VpnInstances.class)
2067             .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
2068     }
2069
2070     @Nonnull
2071     public static List<String> getListOfRdsFromVpnInstance(VpnInstance vpnInstance) {
2072         VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
2073         return vpnConfig.getRouteDistinguisher() != null ? new ArrayList<>(
2074                 vpnConfig.getRouteDistinguisher()) : new ArrayList<>();
2075     }
2076
2077     public static long getVpnIdFromExternalSubnet(DataBroker dataBroker, String routerName, String externalIpAddress) {
2078         if (routerName != null) {
2079             Routers extRouter = NatUtil.getRoutersFromConfigDS(dataBroker, routerName);
2080             if (extRouter != null) {
2081                 return getExternalSubnetVpnIdForRouterExternalIp(dataBroker, externalIpAddress, extRouter);
2082             }
2083         }
2084
2085         return NatConstants.INVALID_ID;
2086     }
2087
2088     public static String validateAndAddNetworkMask(String ipAddress) {
2089         return ipAddress.contains("/32") ? ipAddress : ipAddress + "/32";
2090     }
2091
2092     public static InstanceIdentifier<VpnInterfaceOpDataEntry> getVpnInterfaceOpDataEntryIdentifier(
2093             String vpnInterfaceName, String vpnName) {
2094         return InstanceIdentifier.builder(VpnInterfaceOpData.class).child(VpnInterfaceOpDataEntry.class,
2095         new VpnInterfaceOpDataEntryKey(vpnInterfaceName, vpnName)).build();
2096     }
2097
2098     @Nullable
2099     public static VpnInstanceOpDataEntry getVpnInstanceOpData(DataBroker broker, String rd) {
2100         InstanceIdentifier<VpnInstanceOpDataEntry> id = NatUtil.getVpnInstanceOpDataIdentifier(rd);
2101         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
2102                  broker, LogicalDatastoreType.OPERATIONAL, id).orNull();
2103     }
2104
2105     public static boolean checkForRoutersWithSameExtNetAndNaptSwitch(DataBroker broker, Uuid networkId,
2106                                                                      String routerName, BigInteger dpnId) {
2107         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
2108         Optional<Networks> networkData = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
2109
2110         if (networkData != null && networkData.isPresent()) {
2111             List<Uuid> routerUuidList = networkData.get().getRouterIds();
2112             if (routerUuidList != null && !routerUuidList.isEmpty()) {
2113                 for (Uuid routerUuid : routerUuidList) {
2114                     String sharedRouterName = routerUuid.getValue();
2115                     if (!routerName.equals(sharedRouterName)) {
2116                         BigInteger switchDpnId = NatUtil.getPrimaryNaptfromRouterName(broker, sharedRouterName);
2117                         if (switchDpnId != null && switchDpnId.equals(dpnId)) {
2118                             LOG.debug("checkForRoutersWithSameExtNetAndNaptSwitch: external-network {} is "
2119                                     + "associated with other active router {} on NAPT switch {}", networkId,
2120                                     sharedRouterName, switchDpnId);
2121                             return true;
2122                         }
2123                     }
2124                 }
2125             }
2126         }
2127         return false;
2128     }
2129
2130     public static boolean checkForRoutersWithSameExtSubnetAndNaptSwitch(DataBroker broker, Uuid externalSubnetId,
2131                                                                         String routerName, BigInteger dpnId) {
2132         List<Uuid> routerUuidList = getOptionalExternalSubnets(broker, externalSubnetId).toJavaUtil()
2133             .map(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external
2134                 .subnets.Subnets::getRouterIds).orElse(emptyList());
2135         if (!routerUuidList.isEmpty()) {
2136             for (Uuid routerUuid : routerUuidList) {
2137                 String sharedRouterName = routerUuid.getValue();
2138                 if (!routerName.equals(sharedRouterName)) {
2139                     BigInteger switchDpnId = NatUtil.getPrimaryNaptfromRouterName(broker, sharedRouterName);
2140                     if (switchDpnId != null && switchDpnId.equals(dpnId)) {
2141                         LOG.debug("checkForRoutersWithSameExtSubnetAndNaptSwitch: external-subnetwork {} is "
2142                                   + "associated with other active router {} on NAPT switch {}", externalSubnetId,
2143                             sharedRouterName, switchDpnId);
2144                         return true;
2145                     }
2146                 }
2147             }
2148         }
2149         return false;
2150     }
2151
2152     public static void installRouterGwFlows(ManagedNewTransactionRunner txRunner, IVpnManager vpnManager,
2153             Routers router, BigInteger primarySwitchId, int addOrRemove) {
2154         ListenableFutures.addErrorLogging(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, tx -> {
2155             List<ExternalIps> externalIps = router.getExternalIps();
2156             List<String> externalIpsSting = new ArrayList<>();
2157
2158             if (externalIps == null || externalIps.isEmpty()) {
2159                 LOG.error("installRouterGwFlows: setupRouterGwFlows no externalIP present");
2160                 return;
2161             }
2162             for (ExternalIps externalIp : externalIps) {
2163                 externalIpsSting.add(externalIp.getIpAddress());
2164             }
2165             Uuid subnetVpnName = externalIps.get(0).getSubnetId();
2166             if (addOrRemove == NwConstants.ADD_FLOW) {
2167                 vpnManager.addRouterGwMacFlow(router.getRouterName(), router.getExtGwMacAddress(), primarySwitchId,
2168                         router.getNetworkId(), subnetVpnName.getValue(), tx);
2169                 vpnManager.addArpResponderFlowsToExternalNetworkIps(router.getRouterName(), externalIpsSting,
2170                         router.getExtGwMacAddress(), primarySwitchId,
2171                         router.getNetworkId());
2172             } else {
2173                 vpnManager.removeRouterGwMacFlow(router.getRouterName(), router.getExtGwMacAddress(), primarySwitchId,
2174                         router.getNetworkId(), subnetVpnName.getValue(), tx);
2175                 vpnManager.removeArpResponderFlowsToExternalNetworkIps(router.getRouterName(), externalIpsSting,
2176                         router.getExtGwMacAddress(), primarySwitchId,
2177                         router.getNetworkId());
2178             }
2179         }), LOG, "Error installing router gateway flows");
2180     }
2181
2182     @SuppressWarnings("checkstyle:IllegalCatch")
2183     public static void removeSNATFromDPN(DataBroker dataBroker, IMdsalApiManager mdsalManager,
2184             IdManagerService idManager, NaptSwitchHA naptSwitchHA, BigInteger dpnId,
2185             String routerName, long routerId, long routerVpnId,
2186             ProviderTypes extNwProvType, TypedReadWriteTransaction<Configuration> confTx)
2187                     throws ExecutionException, InterruptedException {
2188         //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
2189         //remove miss entry to NAPT switch
2190         //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
2191         if (extNwProvType == null) {
2192             return;
2193         }
2194         //Get the external IP labels other than VXLAN provider type. Since label is not applicable for VXLAN
2195         Map<String, Long> externalIpLabel;
2196         if (extNwProvType == ProviderTypes.VXLAN) {
2197             externalIpLabel = null;
2198         } else {
2199             externalIpLabel = NatUtil.getExternalIpsLabelForRouter(dataBroker, routerId);
2200         }
2201         BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterName(dataBroker, routerName);
2202         if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
2203             LOG.error("removeSNATFromDPN : No naptSwitch is selected for router {}", routerName);
2204             return;
2205         }
2206         Collection<String> externalIpCache = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
2207         boolean naptStatus =
2208             naptSwitchHA.isNaptSwitchDown(routerName, routerId, dpnId, naptSwitch, routerVpnId,
2209                     externalIpCache, confTx);
2210         if (!naptStatus) {
2211             LOG.debug("removeSNATFromDPN: Switch with DpnId {} is not naptSwitch for router {}",
2212                 dpnId, routerName);
2213             long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
2214             FlowEntity flowEntity = null;
2215             try {
2216                 flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, routerVpnId,
2217                     NatConstants.DEL_FLOW);
2218                 if (flowEntity == null) {
2219                     LOG.error("removeSNATFromDPN : Failed to populate flowentity for router:{} "
2220                             + "with dpnId:{} groupId:{}", routerName, dpnId, groupId);
2221                     return;
2222                 }
2223                 LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity {}", flowEntity);
2224                 mdsalManager.removeFlow(confTx, flowEntity);
2225
2226             } catch (Exception ex) {
2227                 LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
2228                     flowEntity, ex);
2229                 return;
2230             }
2231             LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}",
2232                 dpnId, routerName);
2233
2234             //remove group
2235             GroupEntity groupEntity = null;
2236             try {
2237                 groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
2238                     GroupTypes.GroupAll, emptyList() /*listBucketInfo*/);
2239                 LOG.info("removeSNATFromDPN : Removing NAPT GroupEntity:{}", groupEntity);
2240                 mdsalManager.removeGroup(groupEntity);
2241             } catch (Exception ex) {
2242                 LOG.error("removeSNATFromDPN : Failed to remove group entity {}", groupEntity, ex);
2243                 return;
2244             }
2245             LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routerName {}",
2246                 dpnId, routerName);
2247         } else {
2248             naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, routerId, naptSwitch,
2249                     externalIpLabel, confTx);
2250             //remove table 26 flow ppointing to table46
2251             FlowEntity flowEntity = null;
2252             try {
2253                 flowEntity = naptSwitchHA.buildSnatFlowEntityForNaptSwitch(dpnId, routerName, routerVpnId,
2254                     NatConstants.DEL_FLOW);
2255                 if (flowEntity == null) {
2256                     LOG.error("removeSNATFromDPN : Failed to populate flowentity for router {} with dpnId {}",
2257                             routerName, dpnId);
2258                     return;
2259                 }
2260                 LOG.debug("removeSNATFromDPN : Removing default SNAT miss entry flow entity for router {} with "
2261                     + "dpnId {} in napt switch {}", routerName, dpnId, naptSwitch);
2262                 mdsalManager.removeFlow(confTx, flowEntity);
2263
2264             } catch (Exception ex) {
2265                 LOG.error("removeSNATFromDPN : Failed to remove default SNAT miss entry flow entity {}",
2266                     flowEntity, ex);
2267                 return;
2268             }
2269             LOG.debug("removeSNATFromDPN : Removed default SNAT miss entry flow for dpnID {} with routername {}",
2270                 dpnId, routerName);
2271
2272             //best effort to check IntExt model
2273             naptSwitchHA.bestEffortDeletion(routerId, routerName, externalIpLabel, confTx);
2274         }
2275     }
2276
2277     public static Boolean isOpenStackVniSemanticsEnforcedForGreAndVxlan(IElanService elanManager,
2278                                                                         ProviderTypes extNwProvType) {
2279         if (elanManager.isOpenStackVniSemanticsEnforced() && (extNwProvType == ProviderTypes.GRE
2280                 || extNwProvType == ProviderTypes.VXLAN)) {
2281             return true;
2282         }
2283         return false;
2284     }
2285
2286     public static void addPseudoPortToElanDpn(String elanInstanceName, String pseudoPortId,
2287             BigInteger dpnId, DataBroker dataBroker) {
2288         InstanceIdentifier<DpnInterfaces> elanDpnInterfaceId = getElanDpnInterfaceOperationalDataPath(
2289                 elanInstanceName, dpnId);
2290         // FIXME: separate this out?
2291         final ReentrantLock lock = JvmGlobalLocks.getLockForString(elanInstanceName);
2292         lock.lock();
2293         try {
2294             Optional<DpnInterfaces> dpnInElanInterfaces = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2295                 LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
2296             List<String> elanInterfaceList;
2297             DpnInterfaces dpnInterface;
2298             if (!dpnInElanInterfaces.isPresent()) {
2299                 elanInterfaceList = new ArrayList<>();
2300             } else {
2301                 dpnInterface = dpnInElanInterfaces.get();
2302                 elanInterfaceList = dpnInterface.getInterfaces();
2303             }
2304             if (!elanInterfaceList.contains(pseudoPortId)) {
2305                 elanInterfaceList.add(pseudoPortId);
2306                 dpnInterface = new DpnInterfacesBuilder().setDpId(dpnId).setInterfaces(elanInterfaceList)
2307                         .withKey(new DpnInterfacesKey(dpnId)).build();
2308                 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
2309                     elanDpnInterfaceId, dpnInterface);
2310             }
2311         } catch (ReadFailedException e) {
2312             LOG.warn("Failed to read elanDpnInterface with error {}", e.getMessage());
2313         } catch (TransactionCommitFailedException e) {
2314             LOG.warn("Failed to add elanDpnInterface with error {}", e.getMessage());
2315         } finally {
2316             lock.unlock();
2317         }
2318     }
2319
2320     public static void removePseudoPortFromElanDpn(String elanInstanceName, String pseudoPortId,
2321             BigInteger dpnId, DataBroker dataBroker) {
2322         InstanceIdentifier<DpnInterfaces> elanDpnInterfaceId = getElanDpnInterfaceOperationalDataPath(
2323                 elanInstanceName, dpnId);
2324         // FIXME: separate this out?
2325         final ReentrantLock lock = JvmGlobalLocks.getLockForString(elanInstanceName);
2326         lock.lock();
2327         try {
2328             Optional<DpnInterfaces> dpnInElanInterfaces = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2329                     LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
2330             List<String> elanInterfaceList;
2331             DpnInterfaces dpnInterface;
2332             if (!dpnInElanInterfaces.isPresent()) {
2333                 LOG.info("No interface in any dpn for {}", elanInstanceName);
2334                 return;
2335             }
2336
2337             dpnInterface = dpnInElanInterfaces.get();
2338             elanInterfaceList = dpnInterface.getInterfaces();
2339             if (!elanInterfaceList.contains(pseudoPortId)) {
2340                 LOG.info("Router port not present in DPN {} for VPN {}", dpnId, elanInstanceName);
2341                 return;
2342             }
2343             elanInterfaceList.remove(pseudoPortId);
2344             dpnInterface = new DpnInterfacesBuilder().setDpId(dpnId).setInterfaces(elanInterfaceList)
2345                     .withKey(new DpnInterfacesKey(dpnId)).build();
2346             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
2347                     elanDpnInterfaceId, dpnInterface);
2348         } catch (ReadFailedException e) {
2349             LOG.warn("Failed to read elanDpnInterface with error {}", e.getMessage());
2350         } catch (TransactionCommitFailedException e) {
2351             LOG.warn("Failed to remove elanDpnInterface with error {}", e.getMessage());
2352         } finally {
2353             lock.unlock();
2354         }
2355     }
2356
2357     public static DpnInterfaces getElanInterfaceInfoByElanDpn(String elanInstanceName, BigInteger dpId,
2358             DataBroker broker) {
2359         InstanceIdentifier<DpnInterfaces> elanDpnInterfacesId =
2360                 getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
2361         DpnInterfaces dpnInterfaces = null;
2362         try {
2363             dpnInterfaces = SingleTransactionDataBroker.syncRead(broker, LogicalDatastoreType.OPERATIONAL,
2364                     elanDpnInterfacesId);
2365         }
2366         catch (ReadFailedException e) {
2367             LOG.warn("Failed to read ElanDpnInterfacesList with error {}", e.getMessage());
2368         }
2369         return dpnInterfaces;
2370     }
2371
2372     public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
2373             InstanceIdentifier<T> path) {
2374         try (ReadOnlyTransaction tx = broker.newReadOnlyTransaction()) {
2375             return tx.read(datastoreType, path).get();
2376         } catch (InterruptedException | ExecutionException e) {
2377             throw new RuntimeException(e);
2378         }
2379     }
2380
2381     public static boolean isLastExternalRouter(String networkid, String routerName, NatDataUtil natDataUtil) {
2382         Set<Map.Entry<String,Routers>> extRouter = natDataUtil.getAllRouters();
2383         for (Map.Entry<String,Routers> router : extRouter) {
2384             if (!router.getKey().equals(routerName) && router.getValue().getNetworkId().getValue()
2385                     .equals(networkid)) {
2386                 return false;
2387             }
2388         }
2389         return true;
2390     }
2391
2392     public static InstanceIdentifier<ExtRouters> buildExtRouters() {
2393         InstanceIdentifier<ExtRouters> extRouterInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class)
2394                 .build();
2395         return extRouterInstanceIndentifier;
2396     }
2397
2398     @Nullable
2399     public static LearntVpnVipToPortData getLearntVpnVipToPortData(DataBroker dataBroker) {
2400         try {
2401             return SingleTransactionDataBroker.syncRead(dataBroker,
2402                     LogicalDatastoreType.OPERATIONAL, getLearntVpnVipToPortDataId());
2403         }
2404         catch (ReadFailedException e) {
2405             LOG.warn("Failed to read LearntVpnVipToPortData with error {}", e.getMessage());
2406             return null;
2407         }
2408     }
2409
2410     public static InstanceIdentifier<LearntVpnVipToPortData> getLearntVpnVipToPortDataId() {
2411         InstanceIdentifier<LearntVpnVipToPortData> learntVpnVipToPortDataId = InstanceIdentifier
2412                 .builder(LearntVpnVipToPortData.class).build();
2413         return learntVpnVipToPortDataId;
2414     }
2415
2416     public static InstanceIdentifier<DpnInterfaces> getElanDpnInterfaceOperationalDataPath(String elanInstanceName,
2417             BigInteger dpId) {
2418         return InstanceIdentifier.builder(ElanDpnInterfaces.class)
2419                 .child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName))
2420                 .child(DpnInterfaces.class, new DpnInterfacesKey(dpId)).build();
2421     }
2422
2423     public static InstanceIdentifier<Group> getGroupInstanceId(BigInteger dpnId, long groupId) {
2424         return InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight
2425                 .inventory.rev130819.nodes.Node.class, new NodeKey(new NodeId("openflow:" + dpnId)))
2426                 .augmentation(FlowCapableNode.class).child(Group.class, new GroupKey(new GroupId(groupId))).build();
2427     }
2428
2429     public static void createGroupIdPool(IdManagerService idManager) {
2430         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
2431                 .setPoolName(NatConstants.SNAT_IDPOOL_NAME)
2432                 .setLow(NatConstants.SNAT_ID_LOW_VALUE)
2433                 .setHigh(NatConstants.SNAT_ID_HIGH_VALUE)
2434                 .build();
2435         try {
2436             Future<RpcResult<CreateIdPoolOutput>> result = idManager.createIdPool(createPool);
2437             if (result != null && result.get().isSuccessful()) {
2438                 LOG.debug("createGroupIdPool : GroupIdPool created successfully");
2439             } else {
2440                 LOG.error("createGroupIdPool : Unable to create GroupIdPool");
2441             }
2442         } catch (InterruptedException | ExecutionException e) {
2443             LOG.error("createGroupIdPool : Failed to create PortPool for NAPT Service", e);
2444         }
2445     }
2446
2447     public static boolean getSwitchStatus(DataBroker broker, BigInteger switchId) {
2448         NodeId nodeId = new NodeId("openflow:" + switchId);
2449         LOG.debug("getSwitchStatus : Querying switch with dpnId {} is up/down", nodeId);
2450         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeInstanceId
2451             = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight
2452                     .inventory.rev130819.nodes.Node.class, new NodeKey(nodeId)).build();
2453         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> nodeOptional =
2454                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(broker,
2455                         LogicalDatastoreType.OPERATIONAL, nodeInstanceId);
2456         if (nodeOptional.isPresent()) {
2457             LOG.debug("getSwitchStatus : Switch {} is up", nodeId);
2458             return true;
2459         }
2460         LOG.debug("getSwitchStatus : Switch {} is down", nodeId);
2461         return false;
2462     }
2463
2464     public static boolean isExternalNetwork(DataBroker broker, Uuid networkId) {
2465         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
2466         Optional<Networks> networkData =
2467                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(
2468                         broker, LogicalDatastoreType.CONFIGURATION, id);
2469         return networkData.isPresent();
2470     }
2471
2472     @Nullable
2473     public static String getElanInstancePhysicalNetwok(String elanInstanceName, DataBroker broker) {
2474         ElanInstance elanInstance =  getElanInstanceByName(elanInstanceName, broker);
2475         if (null != elanInstance) {
2476             return elanInstance.getPhysicalNetworkName();
2477         }
2478         return null;
2479
2480     }
2481
2482     public static Map<String, String> getOpenvswitchOtherConfigMap(BigInteger dpnId, DataBroker dataBroker) {
2483         String otherConfigVal = getProviderMappings(dpnId, dataBroker);
2484         return getMultiValueMap(otherConfigVal);
2485     }
2486
2487     public static Map<String, String> getMultiValueMap(String multiKeyValueStr) {
2488         if (Strings.isNullOrEmpty(multiKeyValueStr)) {
2489             return Collections.emptyMap();
2490         }
2491
2492         Map<String, String> valueMap = new HashMap<>();
2493         Splitter splitter = Splitter.on(OTHER_CONFIG_PARAMETERS_DELIMITER);
2494         for (String keyValue : splitter.split(multiKeyValueStr)) {
2495             String[] split = keyValue.split(OTHER_CONFIG_KEY_VALUE_DELIMITER, 2);
2496             if (split.length == 2) {
2497                 valueMap.put(split[0], split[1]);
2498             }
2499         }
2500
2501         return valueMap;
2502     }
2503
2504     public static Optional<Node> getBridgeRefInfo(BigInteger dpnId, DataBroker dataBroker) {
2505         InstanceIdentifier<BridgeRefEntry> bridgeRefInfoPath = InstanceIdentifier.create(BridgeRefInfo.class)
2506                 .child(BridgeRefEntry.class, new BridgeRefEntryKey(dpnId));
2507
2508         Optional<BridgeRefEntry> bridgeRefEntry =
2509                 SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
2510                         LogicalDatastoreType.OPERATIONAL, bridgeRefInfoPath);
2511         if (!bridgeRefEntry.isPresent()) {
2512             LOG.info("getBridgeRefInfo : bridgeRefEntry is not present for {}", dpnId);
2513             return Optional.absent();
2514         }
2515
2516         InstanceIdentifier<Node> nodeId =
2517                 bridgeRefEntry.get().getBridgeReference().getValue().firstIdentifierOf(Node.class);
2518
2519         return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
2520                 LogicalDatastoreType.OPERATIONAL, nodeId);
2521     }
2522
2523     @Nullable
2524     public static String getProviderMappings(BigInteger dpId, DataBroker dataBroker) {
2525         return getBridgeRefInfo(dpId, dataBroker).toJavaUtil().map(node -> getOpenvswitchOtherConfigs(node,
2526                 PROVIDER_MAPPINGS, dataBroker)).orElse(null);
2527     }
2528
2529     @Nullable
2530     public static String getOpenvswitchOtherConfigs(Node node, String key, DataBroker dataBroker) {
2531         OvsdbNodeAugmentation ovsdbNode = node.augmentation(OvsdbNodeAugmentation.class);
2532         if (ovsdbNode == null) {
2533             Optional<Node> nodeFromReadOvsdbNode = readOvsdbNode(node, dataBroker);
2534             if (nodeFromReadOvsdbNode.isPresent()) {
2535                 ovsdbNode = nodeFromReadOvsdbNode.get().augmentation(OvsdbNodeAugmentation.class);
2536             }
2537         }
2538
2539         if (ovsdbNode != null && ovsdbNode.getOpenvswitchOtherConfigs() != null) {
2540             for (OpenvswitchOtherConfigs openvswitchOtherConfigs : ovsdbNode.getOpenvswitchOtherConfigs()) {
2541                 if (Objects.equals(openvswitchOtherConfigs.getOtherConfigKey(), key)) {
2542                     return openvswitchOtherConfigs.getOtherConfigValue();
2543                 }
2544             }
2545         }
2546         LOG.info("getOpenvswitchOtherConfigs : OtherConfigs is not present for ovsdbNode {}", node.getNodeId());
2547         return null;
2548     }
2549
2550     @Nonnull
2551     public static Optional<Node> readOvsdbNode(Node bridgeNode, DataBroker dataBroker) {
2552         OvsdbBridgeAugmentation bridgeAugmentation = extractBridgeAugmentation(bridgeNode);
2553         if (bridgeAugmentation != null) {
2554             InstanceIdentifier<Node> ovsdbNodeIid =
2555                     (InstanceIdentifier<Node>) bridgeAugmentation.getManagedBy().getValue();
2556             return SingleTransactionDataBroker.syncReadOptionalAndTreatReadFailedExceptionAsAbsentOptional(dataBroker,
2557                     LogicalDatastoreType.OPERATIONAL, ovsdbNodeIid);
2558         }
2559         return Optional.absent();
2560
2561     }
2562
2563     @Nullable
2564     public static OvsdbBridgeAugmentation extractBridgeAugmentation(Node node) {
2565         if (node == null) {
2566             return null;
2567         }
2568         return node.augmentation(OvsdbBridgeAugmentation.class);
2569     }
2570
2571     public static String getDefaultFibRouteToSNATForSubnetJobKey(String subnetName, BigInteger dpnId) {
2572         return NatConstants.NAT_DJC_PREFIX + subnetName + dpnId;
2573     }
2574
2575     public static ExternalSubnets getExternalSubnets(DataBroker dataBroker) {
2576         InstanceIdentifier<ExternalSubnets> subnetsIdentifier =
2577                 InstanceIdentifier.builder(ExternalSubnets.class)
2578                 .build();
2579         try {
2580             Optional<ExternalSubnets> optionalExternalSubnets  = SingleTransactionDataBroker
2581                     .syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetsIdentifier);
2582             if (optionalExternalSubnets.isPresent()) {
2583                 return optionalExternalSubnets.get();
2584             }
2585         } catch (ReadFailedException e) {
2586             LOG.error("Failed to read the subnets from the datastore.");
2587         }
2588         return null;
2589
2590     }
2591
2592     public static void addFlow(TypedWriteTransaction<Configuration> confTx, IMdsalApiManager mdsalManager,
2593             BigInteger dpId, short tableId, String flowId, int priority, String flowName, BigInteger cookie,
2594             List<? extends MatchInfoBase> matches, List<InstructionInfo> instructions) {
2595         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority, flowName,
2596                 NatConstants.DEFAULT_IDLE_TIMEOUT, NatConstants.DEFAULT_IDLE_TIMEOUT, cookie, matches,
2597                 instructions);
2598         LOG.trace("syncFlow : Installing DpnId {}, flowId {}", dpId, flowId);
2599         mdsalManager.addFlow(confTx, flowEntity);
2600     }
2601
2602     public static void removeFlow(TypedReadWriteTransaction<Configuration> confTx, IMdsalApiManager mdsalManager,
2603             BigInteger dpId, short tableId, String flowId) throws ExecutionException, InterruptedException {
2604         LOG.trace("syncFlow : Removing Acl Flow DpnId {}, flowId {}", dpId, flowId);
2605         mdsalManager.removeFlow(confTx, dpId, flowId, tableId);
2606     }
2607
2608     public static String getIpv6FlowRef(BigInteger dpnId, short tableId, long routerID) {
2609         return new StringBuilder().append(NatConstants.IPV6_FLOWID_PREFIX).append(dpnId).append(NatConstants
2610                 .FLOWID_SEPARATOR).append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
2611     }
2612
2613     public static String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId,
2614                                                 ItmRpcService itmManager) {
2615         Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
2616         RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
2617         try {
2618             Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager
2619                     .getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder().setSourceDpid(srcDpId)
2620                             .setDestinationDpid(dstDpId).setTunnelType(tunType).build());
2621             rpcResult = result.get();
2622             if (!rpcResult.isSuccessful()) {
2623                 tunType = TunnelTypeGre.class ;
2624                 result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
2625                         .setSourceDpid(srcDpId)
2626                         .setDestinationDpid(dstDpId)
2627                         .setTunnelType(tunType)
2628                         .build());
2629                 rpcResult = result.get();
2630                 if (!rpcResult.isSuccessful()) {
2631                     LOG.warn("getTunnelInterfaceName : RPC Call to getTunnelInterfaceId returned with Errors {}",
2632                             rpcResult.getErrors());
2633                 } else {
2634                     return rpcResult.getResult().getInterfaceName();
2635                 }
2636                 LOG.warn("getTunnelInterfaceName : RPC Call to getTunnelInterfaceId returned with Errors {}",
2637                         rpcResult.getErrors());
2638             } else {
2639                 return rpcResult.getResult().getInterfaceName();
2640             }
2641         } catch (InterruptedException | ExecutionException | NullPointerException e) {
2642             LOG.error("getTunnelInterfaceName : Exception when getting tunnel interface Id for tunnel "
2643                     + "between {} and {}", srcDpId, dstDpId);
2644         }
2645         return null;
2646     }
2647
2648     public static String getIpv6JobKey(String routerName) {
2649         return "Ipv6." + routerName;
2650     }
2651
2652     static ReentrantLock lockForNat(final BigInteger dataPath) {
2653         // FIXME: wrap this in an Identifier
2654         return JvmGlobalLocks.getLockForString(NatConstants.NAT_DJC_PREFIX + dataPath);
2655     }
2656 }