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