Bug 7081 - NAPT is not functional
[netvirt.git] / vpnservice / natservice / natservice-impl / src / main / java / org / opendaylight / netvirt / natservice / internal / NatUtil.java
1 /*
2  * Copyright (c) 2016 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 java.math.BigInteger;
12
13 import com.google.common.collect.Lists;
14 import com.google.common.collect.Sets;
15
16 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
17 import org.opendaylight.genius.mdsalutil.MDSALUtil;
18 import org.opendaylight.genius.mdsalutil.NwConstants;
19 import org.opendaylight.genius.mdsalutil.ActionInfo;
20 import org.opendaylight.genius.mdsalutil.ActionType;
21 import org.opendaylight.genius.mdsalutil.FlowEntity;
22 import org.opendaylight.genius.mdsalutil.MatchInfo;
23 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
24 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
25 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
26 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
27 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
28 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCase;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInputBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpPortInfo;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpMap;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterIdName;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterToVpnMapping;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.SnatintIpPortMap;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCountersKey;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMapKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMapping;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingKey;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolTypeKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapKey;
74 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;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIds;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.to.vpn.mapping.Routermapping;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.to.vpn.mapping.RoutermappingKey;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMap;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMapKey;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPortKey;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeKey;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkMaps;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionResubmitRpcAddGroupCase;
110 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;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
112 import org.opendaylight.yangtools.yang.binding.DataObject;
113 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
114 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
115 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
116 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
117 import com.google.common.base.Optional;
118 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
119 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPortsKey;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.PortsKey;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsKey;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
138 import org.opendaylight.yangtools.yang.common.RpcResult;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersList;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersListKey;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersList;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.DpnRoutersListBuilder;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersListBuilder;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpn.routers.dpn.routers.list.RoutersListKey;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.DpnRouters;
150 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
151 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
152 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
153
154 import org.slf4j.Logger;
155 import org.slf4j.LoggerFactory;
156
157 import java.net.InetAddress;
158 import java.net.UnknownHostException;
159 import java.util.ArrayList;
160 import java.util.Arrays;
161 import java.util.Collections;
162 import java.util.HashMap;
163 import java.util.HashSet;
164 import java.util.List;
165 import java.util.Objects;
166 import java.util.Set;
167 import java.util.concurrent.ExecutionException;
168 import java.util.concurrent.Future;
169 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
170 import com.google.common.util.concurrent.FutureCallback;
171 import com.google.common.util.concurrent.Futures;
172
173 public class NatUtil {
174
175     private static String OF_URI_SEPARATOR = ":";
176     private static final Logger LOG = LoggerFactory.getLogger(NatUtil.class);
177
178     /*
179         getCookieSnatFlow() computes and returns a unique cookie value for the NAT flows using the router ID as the reference value.
180      */
181     public static BigInteger getCookieSnatFlow(long routerId) {
182         return NatConstants.COOKIE_NAPT_BASE.add(new BigInteger("0110000", 16)).add(
183                 BigInteger.valueOf(routerId));
184     }
185
186     /*
187         getCookieNaptFlow() computes and returns a unique cookie value for the NAPT flows using the router ID as the reference value.
188     */
189     public static BigInteger getCookieNaptFlow(long routerId) {
190         return NatConstants.COOKIE_NAPT_BASE.add(new BigInteger("0111000", 16)).add(
191                 BigInteger.valueOf(routerId));
192     }
193
194     /*
195         getVpnId() returns the VPN ID from the VPN name
196      */
197     public static long getVpnId(DataBroker broker, String vpnName) {
198         if(vpnName == null) {
199             return NatConstants.INVALID_ID;
200         }
201
202         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
203                 = getVpnInstanceToVpnIdIdentifier(vpnName);
204         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
205                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
206
207
208         long vpnId = NatConstants.INVALID_ID;
209         if(vpnInstance.isPresent()) {
210             Long vpnIdAsLong = vpnInstance.get().getVpnId();
211             if(vpnIdAsLong != null){
212                 vpnId = vpnIdAsLong;
213             }
214         }
215         return vpnId;
216     }
217
218     public static Long getVpnId(DataBroker broker, long routerId){
219         //Get the external network ID from the ExternalRouter model
220         Uuid networkId = NatUtil.getNetworkIdFromRouterId(broker, routerId);
221         if(networkId == null ){
222             LOG.error("NAT Service : networkId is null");
223             return null;
224         }
225
226         //Get the VPN ID from the ExternalNetworks model
227         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(broker, networkId);
228         if(vpnUuid == null ){
229             LOG.error("NAT Service : vpnUuid is null");
230             return null;
231         }
232         Long vpnId = NatUtil.getVpnId(broker, vpnUuid.getValue());
233         return vpnId;
234     }
235
236     static InstanceIdentifier<RouterPorts> getRouterPortsId(String routerId) {
237         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId)).build();
238     }
239
240     static InstanceIdentifier<Routermapping> getRouterVpnMappingId(String routerId) {
241         return InstanceIdentifier.builder(RouterToVpnMapping.class).child(Routermapping.class, new RoutermappingKey(routerId)).build();
242     }
243
244     static InstanceIdentifier<Ports> getPortsIdentifier(String routerId, String portName) {
245         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId))
246                 .child(Ports.class, new PortsKey(portName)).build();
247     }
248
249     static InstanceIdentifier<InternalToExternalPortMap> getIntExtPortMapIdentifier(String routerId, String portName,
250                                                                                     String internalIp) {
251         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId))
252                 .child(Ports.class, new PortsKey(portName))
253                 .child(InternalToExternalPortMap.class, new InternalToExternalPortMapKey(internalIp)).build();
254     }
255
256     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
257     getVpnInstanceToVpnIdIdentifier(String vpnName) {
258         return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
259                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
260                         new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
261     }
262
263     static String getVpnInstanceFromVpnIdentifier(DataBroker broker, long vpnId) {
264         InstanceIdentifier<VpnIds> id = InstanceIdentifier.builder(VpnIdToVpnInstance.class)
265                 .child(VpnIds.class, new VpnIdsKey(Long.valueOf(vpnId))).build();
266         Optional<VpnIds> vpnInstance = read(broker, LogicalDatastoreType.CONFIGURATION, id);
267         return vpnInstance.isPresent() ? vpnInstance.get().getVpnInstanceName() : null;
268     }
269
270     /*
271        getFlowRef() returns a string identfier for the SNAT flows using the router ID as the reference.
272     */
273     public static String getFlowRef(BigInteger dpnId, short tableId, long routerID, String ip) {
274         return new StringBuffer().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
275                 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID)
276                 .append(NatConstants.FLOWID_SEPARATOR).append(ip).toString();
277     }
278
279     public static String getNaptFlowRef(BigInteger dpnId, short tableId, String routerID, String ip, int port) {
280         return new StringBuffer().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
281                 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).append(NatConstants.FLOWID_SEPARATOR).append(ip).
282                 append(NatConstants.FLOWID_SEPARATOR).append(port).toString();
283     }
284
285     /*
286         getNetworkIdFromRouterId() returns the network-id from the below model using the router-id as the key
287                container ext-routers {
288                    list routers {
289                        key router-name;
290                        leaf router-name { type string; }
291                        leaf network-id { type yang:uuid; }
292                        leaf enable-snat { type boolean; }
293                        leaf-list external-ips {
294                             type string; //format - ipaddress\prefixlength
295                        }
296                        leaf-list subnet-ids { type yang:uuid; }
297                    }
298                }
299
300     */
301     static Uuid getNetworkIdFromRouterId(DataBroker broker, long routerId) {
302         String routerName = getRouterName(broker, routerId);
303         InstanceIdentifier id = buildRouterIdentifier(routerName);
304         Optional<Routers> routerData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
305         if (routerData.isPresent()) {
306             return routerData.get().getNetworkId();
307         }
308         return null;
309     }
310
311     static InstanceIdentifier<Routers> buildRouterIdentifier(String routerId) {
312         InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
313                 (Routers.class, new RoutersKey(routerId)).build();
314         return routerInstanceIndentifier;
315     }
316
317     /*
318      * getEnableSnatFromRouterId() returns IsSnatEnabled true is routerID is present in external n/w otherwise returns false
319      */
320     static boolean isSnatEnabledForRouterId(DataBroker broker, String routerId){
321         InstanceIdentifier id = buildRouterIdentifier(routerId);
322         Optional<Routers> routerData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
323         if (routerData.isPresent()) {
324             return routerData.get().isEnableSnat();
325         }
326         return false;
327     }
328     /*
329         getVpnIdfromNetworkId() returns the vpnid from the below model using the network ID as the key.
330             container external-networks {
331                 list networks  {
332                     key id;
333                     leaf id {
334                         type yang:uuid;
335                     }
336                     leaf vpnid { type yang:uuid; }
337                     leaf-list router-ids { type yang:uuid; }
338                     leaf-list subnet-ids{ type yang:uuid; }
339                 }
340             }
341     */
342     public static Uuid getVpnIdfromNetworkId(DataBroker broker, Uuid networkId) {
343         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
344         Optional<Networks> networkData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
345         if (networkData.isPresent()) {
346             return networkData.get().getVpnid();
347         }
348         return null;
349     }
350
351     public static ProviderTypes getProviderTypefromNetworkId(DataBroker broker, Uuid networkId) {
352         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
353         Optional<Networks> networkData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
354         if ((networkData.isPresent()) && (networkData.get() != null)) {
355             return networkData.get().getProviderNetworkType();
356         }
357         return null;
358     }
359
360     public static List<Uuid> getRouterIdsfromNetworkId(DataBroker broker, Uuid networkId) {
361         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
362         Optional<Networks> networkData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
363         return networkData.isPresent() ? networkData.get().getRouterIds() : Collections.emptyList();
364     }
365
366     static String getAssociatedExternalNetwork(DataBroker dataBroker, String routerId) {
367         InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
368         Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
369         if (routerData.isPresent()) {
370             Uuid networkId = routerData.get().getNetworkId();
371             if(networkId != null) {
372                 return networkId.getValue();
373             }
374         }
375         return null;
376     }
377
378     private static InstanceIdentifier<Networks> buildNetworkIdentifier(Uuid networkId) {
379         InstanceIdentifier<Networks> network = InstanceIdentifier.builder(ExternalNetworks.class).child
380                 (Networks.class, new NetworksKey(networkId)).build();
381         return network;
382     }
383
384
385
386
387     /*
388         getNaptSwitchesDpnIdsfromRouterId() returns the primary-switch-id and the secondary-switch-id in a array using the router-id; as the key.
389             container napt-switches {
390                 list router-to-napt-switch {
391                     key router-id;
392                     leaf router-id { type uint32; }
393                     leaf primary-switch-id { type uint64; }
394                     leaf secondary-switch-id { type uint64; }
395                 }
396             }
397     */
398     public static BigInteger getPrimaryNaptfromRouterId(DataBroker broker, Long routerId) {
399         // convert routerId to Name
400         String routerName = getRouterName(broker, routerId);
401         InstanceIdentifier id = buildNaptSwitchIdentifier(routerName);
402         Optional<RouterToNaptSwitch> routerToNaptSwitchData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
403         if (routerToNaptSwitchData.isPresent()) {
404             RouterToNaptSwitch routerToNaptSwitchInstance = routerToNaptSwitchData.get();
405             return routerToNaptSwitchInstance.getPrimarySwitchId();
406         }
407         return null;
408     }
409
410     private static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchIdentifier(String routerId) {
411         InstanceIdentifier<RouterToNaptSwitch> rtrNaptSw = InstanceIdentifier.builder(NaptSwitches.class).child
412                 (RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerId)).build();
413         return rtrNaptSw;
414     }
415
416     public static String getRouterName(DataBroker broker, Long routerId) {
417         InstanceIdentifier id = buildRouterIdentifier(routerId);
418         Optional<RouterIds> routerIdsData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
419         if (routerIdsData.isPresent()) {
420             RouterIds routerIdsInstance = routerIdsData.get();
421             return routerIdsInstance.getRouterName();
422         }
423         return null;
424     }
425
426     private static InstanceIdentifier<RouterIds> buildRouterIdentifier(Long routerId) {
427         InstanceIdentifier<RouterIds> routerIds = InstanceIdentifier.builder(RouterIdName.class).child
428                 (RouterIds.class, new RouterIdsKey(routerId)).build();
429         return routerIds;
430     }
431
432     public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
433                                                           InstanceIdentifier<T> path) {
434
435         ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
436
437         Optional<T> result = Optional.absent();
438         try {
439             result = tx.read(datastoreType, path).get();
440         } catch (Exception e) {
441             throw new RuntimeException(e);
442         }
443
444         return result;
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
454         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
455                 = getVpnInstanceToVpnIdIdentifier(vpnName);
456         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
457                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
458
459         long vpnId = NatConstants.INVALID_ID;
460         if(vpnInstance.isPresent()) {
461             vpnId = vpnInstance.get().getVpnId();
462         }
463         return vpnId;
464     }
465
466     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, BigInteger cookie) {
467         FlowEntity flowEntity = new FlowEntity(dpnId);
468         flowEntity.setTableId(tableId);
469         flowEntity.setCookie(cookie);
470         return flowEntity;
471     }
472
473     public static long getIpAddress(byte[] rawIpAddress) {
474         return (((rawIpAddress[0] & 0xFF) << (3 * 8)) + ((rawIpAddress[1] & 0xFF) << (2 * 8))
475                 + ((rawIpAddress[2] & 0xFF) << (1 * 8)) + (rawIpAddress[3] & 0xFF)) & 0xffffffffL;
476     }
477
478     public static String getFlowRef(BigInteger dpnId, short tableId, InetAddress destPrefix) {
479         return new StringBuilder(64).append(NatConstants.FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
480                 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
481                 .append(destPrefix.getHostAddress()).toString();
482     }
483
484     public static String getEndpointIpAddressForDPN(DataBroker broker, BigInteger dpnId) {
485         String nextHopIp = null;
486         InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
487                 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpnId)).build();
488         Optional<DPNTEPsInfo> tunnelInfo = read(broker, LogicalDatastoreType.CONFIGURATION, tunnelInfoId);
489         if (tunnelInfo.isPresent()) {
490             List<TunnelEndPoints> nexthopIpList = tunnelInfo.get().getTunnelEndPoints();
491             if (nexthopIpList != null && !nexthopIpList.isEmpty()) {
492                 nextHopIp = nexthopIpList.get(0).getIpAddress().getIpv4Address().getValue();
493             }
494         }
495         return nextHopIp;
496     }
497
498     /*
499         getVpnRd returns the rd (route distinguisher) which is the VRF ID from the below model using the vpnName
500             list vpn-instance {
501                 key "vpn-instance-name"
502                 leaf vpn-instance-name {
503                     type string;
504                 }
505                 leaf vpn-id {
506                     type uint32;
507                 }
508                 leaf vrf-id {
509                     type string;
510                 }
511             }
512     */
513     public static String getVpnRd(DataBroker broker, String vpnName) {
514
515         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
516                 = getVpnInstanceToVpnIdIdentifier(vpnName);
517         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
518                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
519
520         String rd = null;
521         if(vpnInstance.isPresent()) {
522             rd = vpnInstance.get().getVrfId();
523         }
524         return rd;
525     }
526
527     /*  getExternalIPPortMap() returns the internal IP and the port for the querried router ID, external IP and the port.
528         container intext-ip-port-map {
529         config true;
530         list ip-port-mapping {
531             key router-id;
532             leaf router-id { type uint32; }
533             list intext-ip-protocol-type {
534                 key protocol;
535                 leaf protocol { type protocol-types; }
536                 list ip-port-map {
537                     key ip-port-internal;
538                     description "internal to external ip-port mapping";
539                     leaf ip-port-internal { type string; }
540                     container ip-port-external {
541                        uses ip-port-entity;
542                     }
543                 }
544             }
545          }
546        }
547     */
548     public static IpPortExternal getExternalIpPortMap(DataBroker broker, Long routerId, String internalIpAddress, String internalPort, NAPTEntryEvent.Protocol protocol) {
549         ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
550         InstanceIdentifier ipPortMapId = buildIpToPortMapIdentifier(routerId, internalIpAddress, internalPort, protocolType);
551         Optional<IpPortMap> ipPortMapData = read(broker, LogicalDatastoreType.CONFIGURATION, ipPortMapId);
552         if (ipPortMapData.isPresent()) {
553             IpPortMap ipPortMapInstance = ipPortMapData.get();
554             return ipPortMapInstance.getIpPortExternal();
555         }
556         return null;
557     }
558
559     private static InstanceIdentifier<IpPortMap> buildIpToPortMapIdentifier(Long routerId, String internalIpAddress, String internalPort , ProtocolTypes protocolType) {
560         InstanceIdentifier<IpPortMap> ipPortMapId = InstanceIdentifier.builder(IntextIpPortMap.class).child
561                 (IpPortMapping.class, new IpPortMappingKey(routerId)).child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
562                 .child(IpPortMap.class, new IpPortMapKey(internalIpAddress + ":" + internalPort)).build();
563         return ipPortMapId;
564     }
565
566     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId, int priority, String flowName,
567                                              BigInteger cookie, List<MatchInfo> listMatchInfo) {
568
569         FlowEntity flowEntity = new FlowEntity(dpnId);
570         flowEntity.setTableId(tableId);
571         flowEntity.setFlowId(flowId);
572         flowEntity.setPriority(priority);
573         flowEntity.setFlowName(flowName);
574         flowEntity.setCookie(cookie);
575         flowEntity.setMatchInfoList(listMatchInfo);
576         return flowEntity;
577     }
578
579     static boolean isVpnInterfaceConfigured(DataBroker broker, String interfaceName)
580     {
581         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
582         Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
583
584         if (configuredVpnInterface.isPresent()) {
585             return true;
586         }
587         return false;
588     }
589
590     static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
591         return InstanceIdentifier.builder(VpnInterfaces.class)
592                 .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build();
593     }
594
595     static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
596         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
597         Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
598
599         if (configuredVpnInterface.isPresent()) {
600             return configuredVpnInterface.get();
601         }
602         return null;
603     }
604
605     public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
606         /*
607          * NodeConnectorId is of form 'openflow:dpnid:portnum'
608          */
609         String[] split = portId.getValue().split(OF_URI_SEPARATOR);
610         if (split == null || split.length != 3) {
611             return null;
612         }
613         return split[1];
614     }
615
616     public static BigInteger getDpIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
617         String lowerLayerIf = ifState.getLowerLayerIf().get(0);
618         NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
619         return new BigInteger(getDpnFromNodeConnectorId(nodeConnectorId));
620     }
621
622     /*
623     container vpnMaps {
624         list vpnMap {
625             key vpn-id;
626             leaf vpn-id {
627                 type    yang:uuid;
628                 description "vpn-id";
629             }
630             leaf name {
631                 type  string;
632                 description "vpn name";
633             }
634             leaf tenant-id {
635                 type    yang:uuid;
636                 description "The UUID of the tenant that will own the subnet.";
637             }
638
639             leaf router-id {
640               type    yang:uuid;
641               description "UUID of router ";
642             }
643             leaf-list network_ids {
644               type    yang:uuid;
645               description "UUID representing the network ";
646             }
647         }
648     }
649     Method returns router Id associated to a VPN
650      */
651
652     public static String getRouterIdfromVpnInstance(DataBroker broker,String vpnName){
653         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
654                 .child(VpnMap.class, new VpnMapKey(new Uuid(vpnName))).build();
655         Optional<VpnMap> optionalVpnMap = read(broker, LogicalDatastoreType.CONFIGURATION,
656                 vpnMapIdentifier);
657         if (optionalVpnMap.isPresent()) {
658             Uuid routerId = optionalVpnMap.get().getRouterId();
659             if (routerId != null) {
660                 return routerId.getValue();
661             }
662         }
663         return null;
664     }
665
666     static Uuid getVpnForRouter(DataBroker broker, String routerId) {
667         InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
668         Optional<VpnMaps> optionalVpnMaps = read(broker, LogicalDatastoreType.CONFIGURATION,
669                 vpnMapsIdentifier);
670         if (optionalVpnMaps.isPresent() && optionalVpnMaps.get().getVpnMap() != null) {
671             List<VpnMap> allMaps = optionalVpnMaps.get().getVpnMap();
672             if (routerId != null) {
673                 for (VpnMap vpnMap : allMaps) {
674                     if (vpnMap.getRouterId() != null &&
675                             routerId.equals(vpnMap.getRouterId().getValue()) &&
676                             !routerId.equals(vpnMap.getVpnId().getValue())) {
677                         return vpnMap.getVpnId();
678                     }
679                 }
680             }
681         }
682         return null;
683     }
684
685     static long getAssociatedVpn(DataBroker broker, String routerName) {
686         InstanceIdentifier<Routermapping> routerMappingId = NatUtil.getRouterVpnMappingId(routerName);
687         Optional<Routermapping> optRouterMapping = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, routerMappingId);
688         if(optRouterMapping.isPresent()) {
689             Routermapping routerMapping = optRouterMapping.get();
690             return routerMapping.getVpnId();
691         }
692         return NatConstants.INVALID_ID;
693     }
694
695     public static String getAssociatedVPN(DataBroker dataBroker, Uuid networkId, Logger log) {
696         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
697         if(vpnUuid == null ){
698             log.error("No VPN instance associated with ext network {}", networkId);
699             return null;
700         }
701         return vpnUuid.getValue();
702     }
703
704     public static void addPrefixToBGP(DataBroker broker,
705                                       IBgpManager bgpManager,
706                                       IFibManager fibManager,
707                                       String rd,
708                                       String prefix,
709                                       String nextHopIp,
710                                       long label,
711                                       Logger log,
712                                       RouteOrigin origin) {
713         try {
714             LOG.info("ADD: Adding Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
715             if (nextHopIp == null)
716             {
717                 log.error("addPrefix failed since nextHopIp cannot be null.");
718                 return;
719             }
720             fibManager.addOrUpdateFibEntry(broker, rd, prefix, Arrays.asList(nextHopIp), (int)label, origin, null);
721             bgpManager.advertisePrefix(rd, prefix, Arrays.asList(nextHopIp), (int)label);
722             LOG.info("ADD: Added Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
723         } catch(Exception e) {
724             log.error("Add prefix failed", e);
725         }
726     }
727
728     static InstanceIdentifier<Ports> buildPortToIpMapIdentifier(String routerId, String portName) {
729         InstanceIdentifier<Ports> ipPortMapId = InstanceIdentifier.builder(FloatingIpInfo.class).child
730                 (RouterPorts.class, new RouterPortsKey(routerId)).child(Ports.class, new PortsKey(portName)).build();
731         return ipPortMapId;
732     }
733
734     static InstanceIdentifier<RouterPorts> buildRouterPortsIdentifier(String routerId) {
735         InstanceIdentifier<RouterPorts> routerInstanceIndentifier = InstanceIdentifier.builder(FloatingIpInfo.class).child
736                 (RouterPorts.class, new RouterPortsKey(routerId)).build();
737         return routerInstanceIndentifier;
738     }
739
740     /* container snatint-ip-port-map {
741         list intip-port-map {
742             key router-id;
743             leaf router-id { type uint32; }
744             list ip-port {
745                 key internal-ip;
746                 leaf internal-ip { type string; }
747                 list int-ip-proto-type {
748                     key protocol;
749                     leaf protocol { type protocol-types; }
750                     leaf-list ports { type uint16; }
751                 }
752             }
753         }
754     }
755     Method returns InternalIp port List
756     */
757
758     public static List<Integer> getInternalIpPortListInfo(DataBroker dataBroker,Long routerId, String internalIpAddress, ProtocolTypes protocolType){
759         Optional<IntIpProtoType> optionalIpProtoType = read(dataBroker, LogicalDatastoreType.CONFIGURATION, buildSnatIntIpPortIdentifier(routerId, internalIpAddress, protocolType));
760         if (optionalIpProtoType.isPresent()) {
761             return optionalIpProtoType.get().getPorts();
762         }
763         return null;
764     }
765
766     public static InstanceIdentifier<IntIpProtoType> buildSnatIntIpPortIdentifier(Long routerId, String internalIpAddress, ProtocolTypes protocolType) {
767         InstanceIdentifier<IntIpProtoType> intIpProtocolTypeId = InstanceIdentifier.builder(SnatintIpPortMap.class).child
768                 (IntipPortMap.class, new IntipPortMapKey(routerId)).child(IpPort.class, new IpPortKey(internalIpAddress)).child
769                 (IntIpProtoType.class, new IntIpProtoTypeKey(protocolType)).build();
770         return intIpProtocolTypeId;
771     }
772
773     public static ProtocolTypes getProtocolType(NAPTEntryEvent.Protocol protocol) {
774         ProtocolTypes protocolType = ProtocolTypes.TCP.toString().equals(protocol.toString()) ? ProtocolTypes.TCP : ProtocolTypes.UDP;
775         return protocolType;
776     }
777
778     public static InstanceIdentifier<NaptSwitches> getNaptSwitchesIdentifier() {
779         return InstanceIdentifier.create(NaptSwitches.class);
780     }
781
782     public static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchRouterIdentifier(String routerId) {
783         return InstanceIdentifier.create(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerId));
784     }
785
786     public static String toStringIpAddress(byte[] ipAddress, Logger log)
787     {
788         String ip = "";
789         if (ipAddress == null) {
790             return ip;
791         }
792
793         try {
794             ip = InetAddress.getByAddress(ipAddress).getHostAddress();
795         } catch(UnknownHostException e) {
796             log.error("NAT Service : Caught exception during toStringIpAddress()");
797         }
798
799         return ip;
800     }
801
802     public static String getGroupIdKey(String routerName){
803         String groupIdKey = new String("snatmiss." + routerName);
804         return groupIdKey;
805     }
806
807     public static long createGroupId(String groupIdKey,IdManagerService idManager) {
808         AllocateIdInput getIdInput = new AllocateIdInputBuilder()
809                 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
810                 .build();
811         try {
812             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
813             RpcResult<AllocateIdOutput> rpcResult = result.get();
814             return rpcResult.getResult().getIdValue();
815         } catch (NullPointerException | InterruptedException | ExecutionException e) {
816             LOG.trace("", e);
817         }
818         return 0;
819     }
820
821     public static void removePrefixFromBGP(DataBroker broker , IBgpManager bgpManager, IFibManager fibManager, String rd, String prefix, Logger log) {
822         try {
823             LOG.info("REMOVE: Removing Fib entry rd {} prefix {}", rd, prefix);
824             fibManager.removeFibEntry(broker, rd, prefix, null);
825             bgpManager.withdrawPrefix(rd, prefix);
826             LOG.info("REMOVE: Removed Fib entry rd {} prefix {}", rd, prefix);
827         } catch(Exception e) {
828             log.error("Delete prefix failed", e);
829         }
830     }
831
832     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, BigInteger cookie, String flowId) {
833         FlowEntity flowEntity = new FlowEntity(dpnId);
834         flowEntity.setTableId(tableId);
835         flowEntity.setCookie(cookie);
836         flowEntity.setFlowId(flowId);
837         return flowEntity;
838     }
839
840     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId) {
841         FlowEntity flowEntity = new FlowEntity(dpnId);
842         flowEntity.setTableId(tableId);
843         flowEntity.setFlowId(flowId);
844         return flowEntity;
845     }
846
847     public static IpPortMapping getIportMapping(DataBroker broker, long routerId) {
848         Optional<IpPortMapping> getIportMappingData = read(broker, LogicalDatastoreType.CONFIGURATION, getIportMappingIdentifier(routerId));
849         if(getIportMappingData.isPresent()) {
850             return getIportMappingData.get();
851         }
852         return null;
853     }
854
855     public static InstanceIdentifier<IpPortMapping> getIportMappingIdentifier(long routerId) {
856         return InstanceIdentifier.builder(IntextIpPortMap.class).child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
857     }
858
859     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping> getIpMappingBuilder(Long routerId) {
860         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
861                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMappingKey(routerId)).build();
862         return idBuilder;
863     }
864
865     public static List<String> getExternalIpsForRouter(DataBroker dataBroker,Long routerId) {
866         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping> ipMappingOptional = read(dataBroker,
867                 LogicalDatastoreType.OPERATIONAL, getIpMappingBuilder(routerId));
868         List<String> externalIps = new ArrayList<>();
869         if (ipMappingOptional.isPresent()) {
870             List<IpMap> ipMaps = ipMappingOptional.get().getIpMap();
871             for (IpMap ipMap : ipMaps) {
872                 externalIps.add(ipMap.getExternalIp());
873             }
874             //remove duplicates
875             Set<String> uniqueExternalIps = Sets.newHashSet(externalIps);
876             externalIps = Lists.newArrayList(uniqueExternalIps);
877             return externalIps;
878         }
879         return null;
880     }
881
882     public static HashMap<String,Long> getExternalIpsLabelForRouter(DataBroker dataBroker,Long routerId) {
883         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping> ipMappingOptional = read(dataBroker,
884                 LogicalDatastoreType.OPERATIONAL, getIpMappingBuilder(routerId));
885         HashMap<String,Long> externalIpsLabel = new HashMap<>();
886         if (ipMappingOptional.isPresent()) {
887             List<IpMap> ipMaps = ipMappingOptional.get().getIpMap();
888             for (IpMap ipMap : ipMaps) {
889                 externalIpsLabel.put(ipMap.getExternalIp(), ipMap.getLabel());
890             }
891             return externalIpsLabel;
892         }
893         return null;
894     }
895     /*
896     container external-ips-counter {
897         config false;
898         list external-counters{
899             key segment-id;
900             leaf segment-id { type uint32; }
901             list external-ip-counter {
902                 key external-ip;
903                 leaf external-ip { type string; }
904                 leaf counter { type uint8; }
905             }
906         }
907     }
908     */
909
910     public static String getLeastLoadedExternalIp(DataBroker dataBroker, long segmentId){
911         String leastLoadedExternalIp =  null;
912         InstanceIdentifier<ExternalCounters> id = InstanceIdentifier.builder(ExternalIpsCounter.class).child(ExternalCounters.class, new ExternalCountersKey(segmentId)).build();
913         Optional <ExternalCounters> externalCountersData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
914         if (externalCountersData.isPresent()) {
915             ExternalCounters externalCounter = externalCountersData.get();
916             List<ExternalIpCounter> externalIpCounterList = externalCounter.getExternalIpCounter();
917             short countOfLstLoadExtIp = 32767;
918             for(ExternalIpCounter externalIpCounter : externalIpCounterList){
919                 String curExternalIp = externalIpCounter.getExternalIp();
920                 short countOfCurExtIp  = externalIpCounter.getCounter();
921                 if( countOfCurExtIp < countOfLstLoadExtIp ){
922                     countOfLstLoadExtIp = countOfCurExtIp;
923                     leastLoadedExternalIp = curExternalIp;
924                 }
925             }
926         }
927         return leastLoadedExternalIp;
928     }
929
930     public static String[] getSubnetIpAndPrefix(DataBroker dataBroker, Uuid subnetId){
931         String subnetIP = getSubnetIp(dataBroker, subnetId);
932         if(subnetId != null){
933             return getSubnetIpAndPrefix(subnetIP);
934         }
935         return null;
936     }
937
938     public static String getSubnetIp(DataBroker dataBroker, Uuid subnetId){
939         InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
940                 .builder(Subnetmaps.class)
941                 .child(Subnetmap.class, new SubnetmapKey(subnetId))
942                 .build();
943         Optional<Subnetmap> removedSubnet = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
944         if(removedSubnet.isPresent()) {
945             Subnetmap subnetMapEntry = removedSubnet.get();
946             return subnetMapEntry.getSubnetIp();
947         }
948         return null;
949
950     }
951     public static String[] getSubnetIpAndPrefix(String subnetString){
952         String[] subnetSplit = subnetString.split("/");
953         String subnetIp = subnetSplit[0];
954         String subnetPrefix = "0";
955         if (subnetSplit.length == 2) {
956             subnetPrefix = subnetSplit[1];
957         }
958         return new String[] {subnetIp, subnetPrefix};
959     }
960
961     public static String[] getExternalIpAndPrefix(String leastLoadedExtIpAddr){
962         String[] leastLoadedExtIpAddrSplit = leastLoadedExtIpAddr.split("/");
963         String leastLoadedExtIp = leastLoadedExtIpAddrSplit[0];
964         String leastLoadedExtIpPrefix = String.valueOf(NatConstants.DEFAULT_PREFIX);
965         if (leastLoadedExtIpAddrSplit.length == 2) {
966             leastLoadedExtIpPrefix = leastLoadedExtIpAddrSplit[1];
967         }
968         return new String[] {leastLoadedExtIp, leastLoadedExtIpPrefix};
969     }
970
971     public static List<BigInteger> getDpnsForRouter(DataBroker dataBroker, String routerUuid){
972         InstanceIdentifier id = InstanceIdentifier.builder(NeutronRouterDpns.class).child(RouterDpnList.class, new RouterDpnListKey(routerUuid)).build();
973         Optional<RouterDpnList> routerDpnListData = read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
974         List<BigInteger> dpns = new ArrayList<>();
975         if (routerDpnListData.isPresent()) {
976             List<DpnVpninterfacesList> dpnVpninterfacesList = routerDpnListData.get().getDpnVpninterfacesList();
977             for (DpnVpninterfacesList dpnVpnInterface : dpnVpninterfacesList) {
978                 dpns.add(dpnVpnInterface.getDpnId());
979             }
980             return dpns;
981         }
982         return null;
983     }
984
985     public static long getBgpVpnId(DataBroker dataBroker, String routerName){
986         long bgpVpnId = NatConstants.INVALID_ID;
987         Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
988         if(bgpVpnUuid != null){
989             bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
990         }
991         return bgpVpnId;
992     }
993
994     static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterface
995     getConfiguredRouterInterface(DataBroker broker, String interfaceName) {
996         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterface> optRouterInterface =
997                 read(broker, LogicalDatastoreType.CONFIGURATION, NatUtil
998                 .getRouterInterfaceId(interfaceName));
999         if(optRouterInterface.isPresent()) {
1000             return optRouterInterface.get();
1001         }
1002         return null;
1003     }
1004
1005     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterface>
1006     getRouterInterfaceId(String interfaceName) {
1007         return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RouterInterfaces.class)
1008                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterface.class,
1009                         new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterfaceKey(interfaceName)).build();
1010     }
1011
1012     static void addToNeutronRouterDpnsMap(DataBroker broker, String routerName, String interfaceName,
1013                                      OdlInterfaceRpcService ifaceMgrRpcService, WriteTransaction writeOperTxn) {
1014         BigInteger dpId = getDpnForInterface(ifaceMgrRpcService, interfaceName);
1015         if(dpId.equals(BigInteger.ZERO)) {
1016             LOG.warn("NAT Service : Could not retrieve dp id for interface {} to handle router {} association model", interfaceName, routerName);
1017             return;
1018         }
1019
1020         LOG.debug("NAT Service : Adding the Router {} and DPN {} for the Interface {} in the ODL-L3VPN : NeutronRouterDpn map",
1021                 routerName, dpId, interfaceName);
1022         InstanceIdentifier<DpnVpninterfacesList> dpnVpnInterfacesListIdentifier = getRouterDpnId(routerName, dpId);
1023
1024         Optional<DpnVpninterfacesList> optionalDpnVpninterfacesList = read(broker, LogicalDatastoreType
1025                 .OPERATIONAL, dpnVpnInterfacesListIdentifier);
1026         org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces routerInterface =
1027                 new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(interfaceName)).setInterface(interfaceName).build();
1028         if (optionalDpnVpninterfacesList.isPresent()) {
1029             LOG.debug("NAT Service : RouterDpnList already present for the Router {} and DPN {} for the Interface {} in the " +
1030                     "ODL-L3VPN : NeutronRouterDpn map", routerName, dpId, interfaceName);
1031             writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, dpnVpnInterfacesListIdentifier.child(
1032                     org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class, new RouterInterfacesKey(interfaceName)), routerInterface, true);
1033         } else {
1034             LOG.debug("NAT Service : Building new RouterDpnList for the Router {} and DPN {} for the Interface {} in the " +
1035                     "ODL-L3VPN : NeutronRouterDpn map", routerName, dpId, interfaceName);
1036             RouterDpnListBuilder routerDpnListBuilder = new RouterDpnListBuilder();
1037             routerDpnListBuilder.setRouterId(routerName);
1038             DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1039             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces> routerInterfaces =  new ArrayList<>();
1040             routerInterfaces.add(routerInterface);
1041             dpnVpnList.setRouterInterfaces(routerInterfaces);
1042             routerDpnListBuilder.setDpnVpninterfacesList(Arrays.asList(dpnVpnList.build()));
1043             writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1044                     getRouterId(routerName),
1045                     routerDpnListBuilder.build(), true);
1046         }
1047     }
1048
1049     static void addToDpnRoutersMap(DataBroker broker, String routerName, String interfaceName,
1050                                           OdlInterfaceRpcService ifaceMgrRpcService, WriteTransaction writeOperTxn) {
1051         BigInteger dpId = getDpnForInterface(ifaceMgrRpcService, interfaceName);
1052         if(dpId.equals(BigInteger.ZERO)) {
1053             LOG.warn("NAT Service : Could not retrieve dp id for interface {} to handle router {} association model", interfaceName, routerName);
1054             return;
1055         }
1056
1057         LOG.debug("NAT Service : Adding the DPN {} and router {} for the Interface {} in the ODL-L3VPN : " +
1058                         "DPNRouters map",
1059                 dpId, routerName, interfaceName);
1060         InstanceIdentifier<DpnRoutersList> dpnRoutersListIdentifier = getDpnRoutersId(dpId);
1061
1062         Optional<DpnRoutersList> optionalDpnRoutersList = read(broker, LogicalDatastoreType.OPERATIONAL, dpnRoutersListIdentifier);
1063
1064         if (optionalDpnRoutersList.isPresent()) {
1065             RoutersList routersList = new RoutersListBuilder().setKey(new RoutersListKey(routerName)).setRouter(routerName)
1066                     .build();
1067             List<RoutersList> routersListFromDs = optionalDpnRoutersList.get().getRoutersList();
1068             if(!routersListFromDs.contains(routersList)) {
1069                 LOG.debug("NAT Service : Router {} not present for the DPN {}" +
1070                         " in the ODL-L3VPN : DPNRouters map", routerName, dpId);
1071                 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, dpnRoutersListIdentifier.child(RoutersList.class, new
1072                         RoutersListKey(routerName)), routersList, true);
1073             }else{
1074                 LOG.debug("NAT Service : Router {} already mapped to the DPN {} in the ODL-L3VPN : DPNRouters map",
1075                         routerName, dpId);
1076             }
1077         } else {
1078             LOG.debug("NAT Service : Building new DPNRoutersList for the Router {} present in the DPN {} " +
1079                     "ODL-L3VPN : DPNRouters map", routerName, dpId);
1080             DpnRoutersListBuilder dpnRoutersListBuilder = new DpnRoutersListBuilder();
1081             dpnRoutersListBuilder.setDpnId(dpId);
1082             RoutersListBuilder routersListBuilder = new RoutersListBuilder();
1083             routersListBuilder.setRouter(routerName);
1084             dpnRoutersListBuilder.setRoutersList(Arrays.asList(routersListBuilder.build()));
1085             writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1086                     getDpnRoutersId(dpId),
1087                     dpnRoutersListBuilder.build(), true);
1088         }
1089     }
1090
1091     static void removeFromNeutronRouterDpnsMap(DataBroker broker, String routerName, String interfaceName,
1092                                                   BigInteger dpId, WriteTransaction writeOperTxn) {
1093         if(dpId.equals(BigInteger.ZERO)) {
1094             LOG.warn("NAT Service : Could not retrieve dp id for interface {} to handle router {} dissociation model", interfaceName, routerName);
1095             return;
1096         }
1097         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1098         Optional<DpnVpninterfacesList> optionalRouterDpnList = NatUtil.read(broker, LogicalDatastoreType
1099                 .OPERATIONAL, routerDpnListIdentifier);
1100         if (optionalRouterDpnList.isPresent()) {
1101             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1102             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(interfaceName)).setInterface(interfaceName).build();
1103             if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1104                 if (routerInterfaces.isEmpty()) {
1105                     writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1106                 } else {
1107                     writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1108                             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
1109                             new RouterInterfacesKey(interfaceName)));
1110                 }
1111             }
1112         }
1113     }
1114
1115     static void removeFromNeutronRouterDpnsMap(DataBroker broker, String routerName,
1116                                                BigInteger dpId, WriteTransaction writeOperTxn) {
1117         if(dpId.equals(BigInteger.ZERO)) {
1118             LOG.warn("NAT Service : DPN ID is invalid for the router {} ", routerName);
1119             return;
1120         }
1121
1122         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1123         Optional<DpnVpninterfacesList> optionalRouterDpnList = NatUtil.read(broker, LogicalDatastoreType
1124                 .OPERATIONAL, routerDpnListIdentifier);
1125         if (optionalRouterDpnList.isPresent()) {
1126             LOG.debug("NAT Service : Removing the dpn-vpninterfaces-list from the odl-l3vpn:neutron-router-dpns model " +
1127                             "for the router {}", routerName);
1128             writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1129         }else{
1130             LOG.debug("NAT Service : dpn-vpninterfaces-list does not exist in the odl-l3vpn:neutron-router-dpns model " +
1131                     "for the router {}", routerName);
1132         }
1133     }
1134
1135     static void removeFromNeutronRouterDpnsMap(DataBroker broker, String routerName, String vpnInterfaceName,
1136                                                   OdlInterfaceRpcService ifaceMgrRpcService, WriteTransaction writeOperTxn) {
1137         BigInteger dpId = getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1138         if(dpId.equals(BigInteger.ZERO)) {
1139             LOG.warn("NAT Service : Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1140             return;
1141         }
1142         InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1143         Optional<DpnVpninterfacesList> optionalRouterDpnList = read(broker, LogicalDatastoreType
1144                 .OPERATIONAL, routerDpnListIdentifier);
1145         if (optionalRouterDpnList.isPresent()) {
1146             List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1147             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1148
1149             if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1150                 if (routerInterfaces.isEmpty()) {
1151                     if (writeOperTxn != null) {
1152                         writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1153                     } else {
1154                         MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1155                     }
1156                 } else {
1157                     if (writeOperTxn != null) {
1158                         writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1159                                 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
1160                                 new RouterInterfacesKey(vpnInterfaceName)));
1161                     } else {
1162                         MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1163                                 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces.class,
1164                                 new RouterInterfacesKey(vpnInterfaceName)));
1165                     }
1166                 }
1167             }
1168         }
1169     }
1170
1171     static void removeFromDpnRoutersMap(DataBroker broker, String routerName, String vpnInterfaceName,
1172                                         OdlInterfaceRpcService ifaceMgrRpcService, WriteTransaction writeOperTxn) {
1173         BigInteger dpId = getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1174         if (dpId.equals(BigInteger.ZERO)) {
1175             LOG.warn("NAT Service : removeFromDpnRoutersMap() : Could not retrieve DPN ID for interface {} to handle router {} dissociation model",
1176                     vpnInterfaceName, routerName);
1177             return;
1178         }
1179         removeFromDpnRoutersMap(broker, routerName, vpnInterfaceName, dpId, ifaceMgrRpcService, writeOperTxn);
1180     }
1181
1182     static void removeFromDpnRoutersMap(DataBroker broker, String routerName, String vpnInterfaceName, BigInteger curDpnId,
1183                                            OdlInterfaceRpcService ifaceMgrRpcService, WriteTransaction writeOperTxn) {
1184         /*
1185             1) Get the DpnRoutersList for the DPN.
1186             2) Get the RoutersList identifier for the DPN and router.
1187             3) Get the VPN interfaces for the router (routerList) through which it is connected to the DPN.
1188             4) If the removed VPN interface is the only interface through which the router is connected to the DPN,
1189              then remove RouterList.
1190          */
1191
1192         LOG.debug("NAT Service : removeFromDpnRoutersMap() : Removing the DPN {} and router {} for the Interface {}" +
1193                 " in the ODL-L3VPN : DPNRouters map", curDpnId, routerName, vpnInterfaceName);
1194
1195         //Get the dpn-routers-list instance for the current DPN.
1196         InstanceIdentifier<DpnRoutersList> dpnRoutersListIdentifier = getDpnRoutersId(curDpnId);
1197         Optional<DpnRoutersList> dpnRoutersListData = read(broker, LogicalDatastoreType.OPERATIONAL,
1198                 dpnRoutersListIdentifier);
1199
1200         if (dpnRoutersListData == null || !dpnRoutersListData.isPresent()) {
1201             LOG.debug("NAT Service : dpn-routers-list is not present for DPN {} in the ODL-L3VPN:dpn-routers model",
1202                     curDpnId);
1203             return;
1204         }
1205
1206         //Get the routers-list instance for the router on the current DPN only
1207         InstanceIdentifier<RoutersList> routersListIdentifier = getRoutersList(curDpnId, routerName);
1208         Optional<RoutersList> routersListData = read(broker, LogicalDatastoreType.OPERATIONAL, routersListIdentifier);
1209
1210         if (routersListData == null || !routersListData.isPresent()) {
1211             LOG.debug("NAT Service : routers-list is not present for the DPN {} in the ODL-L3VPN:dpn-routers model",
1212                     curDpnId);
1213             return;
1214         }
1215
1216         LOG.debug("NAT Service : Get the interfaces for the router {} from the NeutronVPN - router-interfaces-map",
1217                 routerName);
1218         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.
1219                 interfaces.map.RouterInterfaces> routerInterfacesId = getRoutersInterfacesIdentifier(routerName);
1220         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.
1221                 RouterInterfaces> routerInterfacesData = read(broker, LogicalDatastoreType.CONFIGURATION,
1222                 routerInterfacesId);
1223
1224         if (routerInterfacesData == null || !routerInterfacesData.isPresent()) {
1225             LOG.debug("NAT Service : Unable to get the routers list for the DPN {}. Possibly all subnets removed" +
1226                     " from router {} OR Router {} has been deleted. Hence DPN router model WILL be cleared ", curDpnId,
1227                     routerName, routerName);
1228             writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routersListIdentifier);
1229             return;
1230         }
1231
1232         //Get the VM interfaces for the router on the current DPN only.
1233         List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces> vmInterfaces =
1234                 routerInterfacesData.get().getInterfaces();
1235         if (vmInterfaces == null) {
1236             LOG.debug("NAT Service : VM interfaces are not present for the router {} in the NeutronVPN - router-interfaces-map", routerName);
1237             return;
1238         }
1239
1240         //If the removed VPN interface is the only interface through which the router is connected to the DPN, then remove RouterList.
1241         for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces vmInterface :
1242                 vmInterfaces) {
1243             String vmInterfaceName = vmInterface.getInterfaceId();
1244             BigInteger vmDpnId = getDpnForInterface(ifaceMgrRpcService, vmInterfaceName);
1245             if (vmDpnId.equals(BigInteger.ZERO) || !vmDpnId.equals(curDpnId)) {
1246                 LOG.debug("NAT Service : DPN ID {} for the removed interface {} is not the same as that of the DPN ID for the checked interface {} ",
1247                         curDpnId, vpnInterfaceName, vmDpnId, vmInterfaceName);
1248                 continue;
1249             }
1250             if(!vmInterfaceName.equalsIgnoreCase(vpnInterfaceName)) {
1251                 LOG.debug("NAT Service : Router {} is present in the DPN {} through the other interface {} " +
1252                         "Hence DPN router model WOULD NOT be cleared", routerName, curDpnId, vmInterfaceName);
1253                 return;
1254             }
1255         }
1256         LOG.debug("NAT Service : Router {} is present in the DPN {} only through the interface {} " +
1257                 "Hence DPN router model WILL be cleared. Possibly last VM for the router " +
1258                 "deleted in the DPN", routerName, curDpnId);
1259         writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routersListIdentifier);
1260
1261     }
1262
1263     private static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces>
1264         getRoutersInterfacesIdentifier(String routerName){
1265         return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap.class)
1266                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces.class,
1267                         new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey(new Uuid(routerName)))
1268                 .build();
1269     }
1270
1271     private static InstanceIdentifier<RoutersList> getRoutersList(BigInteger dpnId, String routerName) {
1272         return InstanceIdentifier.builder(DpnRouters.class)
1273                 .child(DpnRoutersList.class, new DpnRoutersListKey(dpnId))
1274                 .child(RoutersList.class, new RoutersListKey(routerName)).build();
1275     }
1276
1277     public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
1278         BigInteger nodeId = BigInteger.ZERO;
1279         try {
1280             GetDpidFromInterfaceInput
1281                     dpIdInput =
1282                     new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
1283             Future<RpcResult<GetDpidFromInterfaceOutput>>
1284                     dpIdOutput =
1285                     interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
1286             RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
1287             if (dpIdResult.isSuccessful()) {
1288                 nodeId = dpIdResult.getResult().getDpid();
1289             } else {
1290                 LOG.error("NAT Service : Could not retrieve DPN Id for interface {}", ifName);
1291             }
1292         } catch (NullPointerException | InterruptedException | ExecutionException e) {
1293             LOG.error("NAT Service : Exception when getting dpn for interface {}", ifName,  e);
1294         }
1295         return nodeId;
1296     }
1297
1298     public static List<ActionInfo> getEgressActionsForInterface(OdlInterfaceRpcService interfaceManager, String ifName,
1299             Long tunnelKey) {
1300         return getEgressActionsForInterface(interfaceManager, ifName, tunnelKey, 0);
1301     }
1302
1303     public static List<ActionInfo> getEgressActionsForInterface(OdlInterfaceRpcService interfaceManager, String ifName,
1304             Long tunnelKey, int pos) {
1305         LOG.debug("NAT Service : getEgressActionsForInterface called for interface {}", ifName);
1306         GetEgressActionsForInterfaceInputBuilder egressActionsBuilder = new GetEgressActionsForInterfaceInputBuilder()
1307                 .setIntfName(ifName);
1308         if (tunnelKey != null) {
1309             egressActionsBuilder.setTunnelKey(tunnelKey);
1310         }
1311
1312         List<ActionInfo> listActionInfo = new ArrayList<>();
1313         try {
1314             Future<RpcResult<GetEgressActionsForInterfaceOutput>> result = interfaceManager
1315                     .getEgressActionsForInterface(egressActionsBuilder.build());
1316             RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
1317             if (!rpcResult.isSuccessful()) {
1318                 LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName,
1319                         rpcResult.getErrors());
1320             } else {
1321                 List<Action> actions = rpcResult.getResult().getAction();
1322                 for (Action action : actions) {
1323                     org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionClass = action
1324                             .getAction();
1325                     if (actionClass instanceof OutputActionCase) {
1326                         listActionInfo
1327                                 .add(new ActionInfo(ActionType.output, new String[] { ((OutputActionCase) actionClass)
1328                                         .getOutputAction().getOutputNodeConnector().getValue() }, pos++));
1329                     } else if (actionClass instanceof PushVlanActionCase) {
1330                         listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {}, pos++));
1331                     } else if (actionClass instanceof SetFieldCase) {
1332                         if (((SetFieldCase) actionClass).getSetField().getVlanMatch() != null) {
1333                             int vlanVid = ((SetFieldCase) actionClass).getSetField().getVlanMatch().getVlanId()
1334                                     .getVlanId().getValue();
1335                             listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid,
1336                                     new String[] { Long.toString(vlanVid) }, pos++));
1337                         }
1338                     } else if (actionClass instanceof NxActionResubmitRpcAddGroupCase) {
1339                         Short tableId = ((NxActionResubmitRpcAddGroupCase)actionClass).getNxResubmit().getTable();
1340                         listActionInfo.add(new ActionInfo(ActionType.nx_resubmit,
1341                             new String[] { tableId.toString() }, pos++));
1342                     } else if (actionClass instanceof NxActionRegLoadNodesNodeTableFlowApplyActionsCase) {
1343                         NxRegLoad nxRegLoad =
1344                             ((NxActionRegLoadNodesNodeTableFlowApplyActionsCase)actionClass).getNxRegLoad();
1345                         listActionInfo.add(new ActionInfo(ActionType.nx_load_reg_6,
1346                             new String[] { nxRegLoad.getDst().getStart().toString(),
1347                                 nxRegLoad.getDst().getEnd().toString(),
1348                                 nxRegLoad.getValue().toString(10)}, pos++));
1349                     }
1350                 }
1351             }
1352         } catch (InterruptedException | ExecutionException e) {
1353             LOG.warn("Exception when egress actions for interface {}", ifName, e);
1354         }
1355         return listActionInfo;
1356     }
1357
1358     public static Port getNeutronPortForRouterGetewayIp(DataBroker broker, IpAddress targetIP) {
1359         return getNeutronPortForIp(broker, targetIP, NeutronConstants.DEVICE_OWNER_GATEWAY_INF);
1360     }
1361
1362     public static List<Port> getNeutronPorts(DataBroker broker) {
1363         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports>
1364         portsIdentifier = InstanceIdentifier
1365                 .create(Neutron.class)
1366                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports.class);
1367         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports> portsOptional = read(
1368                 broker, LogicalDatastoreType.CONFIGURATION, portsIdentifier);
1369
1370         if (!portsOptional.isPresent() || portsOptional.get().getPort() == null) {
1371             LOG.trace("No neutron ports found");
1372             return Collections.EMPTY_LIST;
1373         }
1374
1375         return portsOptional.get().getPort();
1376
1377     }
1378
1379     public static Port getNeutronPortForIp(DataBroker broker,
1380         IpAddress targetIP, String deviceType) {
1381         List<Port> ports = getNeutronPorts(
1382                 broker);
1383
1384         for (Port port : ports) {
1385             if (deviceType.equals(port.getDeviceOwner()) && port.getFixedIps() != null) {
1386                 for (FixedIps ip : port.getFixedIps()) {
1387                     if (Objects.equals(ip.getIpAddress(), targetIP)) {
1388                         return port;
1389                     }
1390                 }
1391             }
1392         }
1393
1394         return null;
1395     }
1396
1397     public static Uuid getSubnetIdForFloatingIp(Port port, IpAddress targetIP) {
1398         if (port == null) {
1399             return null;
1400         }
1401         for (FixedIps ip : port.getFixedIps()) {
1402             if (Objects.equals(ip.getIpAddress(), targetIP)) {
1403                 return ip.getSubnetId();
1404             }
1405         }
1406
1407         return null;
1408     }
1409
1410     public static Subnetmap getSubnetMap(DataBroker broker, Uuid subnetId) {
1411         InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier.builder(Subnetmaps.class)
1412                 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
1413         Optional<Subnetmap> subnetOpt = read(broker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
1414         return subnetOpt.isPresent() ? subnetOpt.get() : null;
1415     }
1416
1417     public static List<Uuid> getSubnetIdsFromNetworkId(DataBroker broker, Uuid networkId) {
1418         InstanceIdentifier<NetworkMap> id = InstanceIdentifier.builder(NetworkMaps.class)
1419                 .child(NetworkMap.class, new NetworkMapKey(networkId)).build();
1420         Optional<NetworkMap> optionalNetworkMap = read(broker, LogicalDatastoreType.CONFIGURATION, id);
1421         return optionalNetworkMap.isPresent() ? optionalNetworkMap.get().getSubnetIdList() : null;
1422     }
1423
1424     public static String getSubnetGwMac(DataBroker broker, Uuid subnetId, String vpnName) {
1425         if (subnetId == null) {
1426             return null;
1427         }
1428
1429         InstanceIdentifier<Subnet> subnetInst = InstanceIdentifier.create(Neutron.class).child(Subnets.class)
1430                 .child(Subnet.class, new SubnetKey(subnetId));
1431         Optional<Subnet> subnetOpt = read(broker, LogicalDatastoreType.CONFIGURATION, subnetInst);
1432         if (!subnetOpt.isPresent()) {
1433             return null;
1434         }
1435
1436         IpAddress gatewayIp = subnetOpt.get().getGatewayIp();
1437         if (gatewayIp == null) {
1438             LOG.trace("No GW ip found for subnet {}", subnetId.getValue());
1439             return null;
1440         }
1441
1442         InstanceIdentifier<VpnPortipToPort> portIpInst = InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
1443                 .child(VpnPortipToPort.class, new VpnPortipToPortKey(gatewayIp.getIpv4Address().getValue(), vpnName))
1444                 .build();
1445         Optional<VpnPortipToPort> portIpToPortOpt = read(broker, LogicalDatastoreType.OPERATIONAL, portIpInst);
1446         if (!portIpToPortOpt.isPresent()) {
1447             LOG.trace("No resolution was found to GW ip {} in subnet {}", gatewayIp, subnetId.getValue());
1448             return null;
1449         }
1450
1451         return portIpToPortOpt.get().getMacAddress();
1452     }
1453
1454     public static boolean isIPv6Subnet(String prefix) {
1455         IpPrefix ipPrefix = new IpPrefix(prefix.toCharArray());
1456         if (ipPrefix.getIpv6Prefix() != null) {
1457             return true;
1458         }
1459         return false;
1460     }
1461
1462     static InstanceIdentifier<DpnRoutersList> getDpnRoutersId(BigInteger dpnId) {
1463         return InstanceIdentifier.builder(DpnRouters.class)
1464                 .child(DpnRoutersList.class, new DpnRoutersListKey(dpnId)).build();
1465     }
1466
1467     static InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1468         return InstanceIdentifier.builder(NeutronRouterDpns.class)
1469                 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1470                 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1471     }
1472
1473     static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface getInterface(DataBroker broker, String interfaceName) {
1474         Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface> optInterface =
1475                 read(broker, LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName));
1476         if(optInterface.isPresent()) {
1477             return optInterface.get();
1478         }
1479         return null;
1480     }
1481
1482     static InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1483         return InstanceIdentifier.builder(NeutronRouterDpns.class)
1484                 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1485     }
1486
1487     protected static String getFloatingIpPortMacFromFloatingIpId(DataBroker broker, Uuid floatingIpId) {
1488         InstanceIdentifier id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
1489         Optional<FloatingIpIdToPortMapping> optFloatingIpIdToPortMapping = read(broker, LogicalDatastoreType
1490                         .CONFIGURATION, id);
1491         if (optFloatingIpIdToPortMapping.isPresent()) {
1492             return optFloatingIpIdToPortMapping.get().getFloatingIpPortMacAddress();
1493         }
1494         return null;
1495     }
1496
1497     protected static Uuid getFloatingIpPortSubnetIdFromFloatingIpId(DataBroker broker, Uuid floatingIpId) {
1498         InstanceIdentifier id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
1499         Optional<FloatingIpIdToPortMapping> optFloatingIpIdToPortMapping = read(broker, LogicalDatastoreType
1500                 .CONFIGURATION, id);
1501         if (optFloatingIpIdToPortMapping.isPresent()) {
1502             return optFloatingIpIdToPortMapping.get().getFloatingIpPortSubnetId();
1503         }
1504         return null;
1505     }
1506
1507     static InstanceIdentifier<FloatingIpIdToPortMapping> buildfloatingIpIdToPortMappingIdentifier (Uuid floatingIpId) {
1508         return InstanceIdentifier.builder(FloatingIpPortInfo.class).child(FloatingIpIdToPortMapping.class, new
1509                 FloatingIpIdToPortMappingKey(floatingIpId)).build();
1510     }
1511
1512     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
1513         return InstanceIdentifier.builder(Interfaces.class)
1514                 .child(
1515                         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface.class, new InterfaceKey(interfaceName)).build();
1516     }
1517     static final FutureCallback<Void> DEFAULT_CALLBACK =
1518             new FutureCallback<Void>() {
1519                 @Override
1520                 public void onSuccess(Void result) {
1521                     LOG.debug("NAT Service : Success in Datastore operation");
1522                 }
1523
1524                 @Override
1525                 public void onFailure(Throwable error) {
1526                     LOG.error("NAT Service : Error in Datastore operation", error);
1527                 }
1528
1529                 ;
1530             };
1531
1532     static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
1533                                                      InstanceIdentifier<T> path) {
1534         delete(broker, datastoreType, path, DEFAULT_CALLBACK);
1535     }
1536
1537    static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
1538                                                      InstanceIdentifier<T> path, FutureCallback<Void> callback) {
1539         WriteTransaction tx = broker.newWriteOnlyTransaction();
1540         tx.delete(datastoreType, path);
1541         Futures.addCallback(tx.submit(), callback);
1542     }
1543     static Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
1544         InstanceIdentifier<Interface> ifStateId =
1545                 buildStateInterfaceId(interfaceName);
1546         Optional<Interface> ifStateOptional = read(dataBroker, LogicalDatastoreType.OPERATIONAL, ifStateId);
1547         if (ifStateOptional.isPresent()) {
1548             return ifStateOptional.get();
1549         }
1550
1551         return null;
1552     }
1553
1554     static InstanceIdentifier<Interface>
1555     buildStateInterfaceId(String interfaceName) {
1556         InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
1557                 InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState.class)
1558                         .child(Interface.class,
1559                                 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
1560         InstanceIdentifier<Interface> id = idBuilder.build();
1561         return id;
1562     }
1563 }