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