Code for myMAC in the L3VPN pipeline
[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.opendaylight.inventory.rev130819.NodeConnectorId;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCase;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInputBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalIpsCounter;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpMap;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.IntextIpPortMap;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProtocolTypes;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterIdName;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.RouterToVpnMapping;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.SnatintIpPortMap;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCounters;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.ExternalCountersKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolTypeKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapKey;
67 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;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIds;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.id.name.RouterIdsKey;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.to.vpn.mapping.Routermapping;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.router.to.vpn.mapping.RoutermappingKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMap;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.IntipPortMapKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPortKey;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeKey;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionResubmitRpcAddGroupCase;
99 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;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
101
102 import org.opendaylight.yangtools.yang.binding.DataObject;
103 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
104 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
105 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
106 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
107 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
108
109 import com.google.common.base.Optional;
110
111 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
112 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPorts;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.RouterPortsKey;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.PortsKey;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsKey;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.IpMappingKey;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
134 import org.opendaylight.yangtools.yang.common.RpcResult;
135 import org.slf4j.Logger;
136 import org.slf4j.LoggerFactory;
137
138 import java.net.InetAddress;
139 import java.net.UnknownHostException;
140 import java.util.ArrayList;
141 import java.util.Arrays;
142 import java.util.Collections;
143 import java.util.HashMap;
144 import java.util.List;
145 import java.util.Objects;
146 import java.util.Set;
147 import java.util.concurrent.ExecutionException;
148 import java.util.concurrent.Future;
149
150
151
152 public class NatUtil {
153
154     private static String OF_URI_SEPARATOR = ":";
155     private static final Logger LOG = LoggerFactory.getLogger(NatUtil.class);
156
157     /*
158         getCookieSnatFlow() computes and returns a unique cookie value for the NAT flows using the router ID as the reference value.
159      */
160     public static BigInteger getCookieSnatFlow(long routerId) {
161         return NatConstants.COOKIE_NAPT_BASE.add(new BigInteger("0110000", 16)).add(
162                 BigInteger.valueOf(routerId));
163     }
164
165     /*
166         getCookieNaptFlow() computes and returns a unique cookie value for the NAPT flows using the router ID as the reference value.
167     */
168     public static BigInteger getCookieNaptFlow(long routerId) {
169         return NatConstants.COOKIE_NAPT_BASE.add(new BigInteger("0111000", 16)).add(
170                 BigInteger.valueOf(routerId));
171     }
172
173     /*
174         getVpnId() returns the VPN ID from the VPN name
175      */
176     public static long getVpnId(DataBroker broker, String vpnName) {
177         if(vpnName == null) {
178             return NatConstants.INVALID_ID;
179         }
180
181         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
182                 = getVpnInstanceToVpnIdIdentifier(vpnName);
183         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
184                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
185
186
187         long vpnId = NatConstants.INVALID_ID;
188         if(vpnInstance.isPresent()) {
189             Long vpnIdAsLong = vpnInstance.get().getVpnId();
190             if(vpnIdAsLong != null){
191                 vpnId = vpnIdAsLong;
192             }
193         }
194         return vpnId;
195     }
196
197     public static Long getVpnId(DataBroker broker, long routerId){
198         //Get the external network ID from the ExternalRouter model
199         Uuid networkId = NatUtil.getNetworkIdFromRouterId(broker, routerId);
200         if(networkId == null ){
201             LOG.error("NAT Service : networkId is null");
202             return null;
203         }
204
205         //Get the VPN ID from the ExternalNetworks model
206         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(broker, networkId);
207         if(vpnUuid == null ){
208             LOG.error("NAT Service : vpnUuid is null");
209             return null;
210         }
211         Long vpnId = NatUtil.getVpnId(broker, vpnUuid.getValue());
212         return vpnId;
213     }
214
215     static InstanceIdentifier<RouterPorts> getRouterPortsId(String routerId) {
216         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId)).build();
217     }
218
219     static InstanceIdentifier<Routermapping> getRouterVpnMappingId(String routerId) {
220         return InstanceIdentifier.builder(RouterToVpnMapping.class).child(Routermapping.class, new RoutermappingKey(routerId)).build();
221     }
222
223     static InstanceIdentifier<Ports> getPortsIdentifier(String routerId, String portName) {
224         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId))
225                 .child(Ports.class, new PortsKey(portName)).build();
226     }
227
228     static InstanceIdentifier<IpMapping> getIpMappingIdentifier(String routerId, String portName, String internalIp) {
229         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId))
230                 .child(Ports.class, new PortsKey(portName))
231                 .child(IpMapping.class, new IpMappingKey(internalIp)).build();
232     }
233
234     /*
235         getVpnInstanceToVpnIdIdentifier() returns the VPN instance from the below model using the VPN name as the key.
236             list vpn-instance {
237                 key "vpn-instance-name"
238                 leaf vpn-instance-name {
239                     type string;
240                 }
241                 leaf vpn-id {
242                     type uint32;
243                 }
244                 leaf vrf-id {
245                     type string;
246                 }
247             }
248     */
249
250     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
251     getVpnInstanceToVpnIdIdentifier(String vpnName) {
252         return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
253                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
254                         new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
255     }
256
257     static String getVpnInstanceFromVpnIdentifier(DataBroker broker, long vpnId) {
258         InstanceIdentifier<VpnIds> id = InstanceIdentifier.builder(VpnIdToVpnInstance.class)
259                 .child(VpnIds.class, new VpnIdsKey(Long.valueOf(vpnId))).build();
260         Optional<VpnIds> vpnInstance = read(broker, LogicalDatastoreType.CONFIGURATION, id);
261         return vpnInstance.isPresent() ? vpnInstance.get().getVpnInstanceName() : null;
262     }
263
264     /*
265        getFlowRef() returns a string identfier for the SNAT flows using the router ID as the reference.
266     */
267     public static String getFlowRef(BigInteger dpnId, short tableId, long routerID, String ip) {
268         return new StringBuffer().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
269                 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID)
270                 .append(NatConstants.FLOWID_SEPARATOR).append(ip).toString();
271     }
272
273     public static String getNaptFlowRef(BigInteger dpnId, short tableId, String routerID, String ip, int port) {
274         return new StringBuffer().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
275                 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).append(NatConstants.FLOWID_SEPARATOR).append(ip).
276                 append(NatConstants.FLOWID_SEPARATOR).append(port).toString();
277     }
278
279     /*
280         getNetworkIdFromRouterId() returns the network-id from the below model using the router-id as the key
281                container ext-routers {
282                    list routers {
283                        key router-name;
284                        leaf router-name { type string; }
285                        leaf network-id { type yang:uuid; }
286                        leaf enable-snat { type boolean; }
287                        leaf-list external-ips {
288                             type string; //format - ipaddress\prefixlength
289                        }
290                        leaf-list subnet-ids { type yang:uuid; }
291                    }
292                }
293
294     */
295     static Uuid getNetworkIdFromRouterId(DataBroker broker, long routerId) {
296         String routerName = getRouterName(broker, routerId);
297         InstanceIdentifier id = buildRouterIdentifier(routerName);
298         Optional<Routers> routerData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
299         if (routerData.isPresent()) {
300             return routerData.get().getNetworkId();
301         }
302         return null;
303     }
304
305     static InstanceIdentifier<Routers> buildRouterIdentifier(String routerId) {
306         InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
307                 (Routers.class, new RoutersKey(routerId)).build();
308         return routerInstanceIndentifier;
309     }
310
311     /*
312      * getEnableSnatFromRouterId() returns IsSnatEnabled true is routerID is present in external n/w otherwise returns false
313      */
314     static boolean isSnatEnabledForRouterId(DataBroker broker, String routerId){
315         InstanceIdentifier id = buildRouterIdentifier(routerId);
316         Optional<Routers> routerData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
317         if (routerData.isPresent()) {
318             return routerData.get().isEnableSnat();
319         }
320         return false;
321     }
322     /*
323         getVpnIdfromNetworkId() returns the vpnid from the below model using the network ID as the key.
324             container external-networks {
325                 list networks  {
326                     key id;
327                     leaf id {
328                         type yang:uuid;
329                     }
330                     leaf vpnid { type yang:uuid; }
331                     leaf-list router-ids { type yang:uuid; }
332                     leaf-list subnet-ids{ type yang:uuid; }
333                 }
334             }
335     */
336     public static Uuid getVpnIdfromNetworkId(DataBroker broker, Uuid networkId) {
337         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
338         Optional<Networks> networkData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
339         if (networkData.isPresent()) {
340             return networkData.get().getVpnid();
341         }
342         return null;
343     }
344
345     public static List<Uuid> getRouterIdsfromNetworkId(DataBroker broker, Uuid networkId) {
346         InstanceIdentifier<Networks> id = buildNetworkIdentifier(networkId);
347         Optional<Networks> networkData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
348         return networkData.isPresent() ? networkData.get().getRouterIds() : Collections.emptyList();
349     }
350
351     static String getAssociatedExternalNetwork(DataBroker dataBroker, String routerId) {
352         InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
353         Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
354         if (routerData.isPresent()) {
355             Uuid networkId = routerData.get().getNetworkId();
356             if(networkId != null) {
357                 return networkId.getValue();
358             }
359         }
360         return null;
361     }
362
363     private static InstanceIdentifier<Networks> buildNetworkIdentifier(Uuid networkId) {
364         InstanceIdentifier<Networks> network = InstanceIdentifier.builder(ExternalNetworks.class).child
365                 (Networks.class, new NetworksKey(networkId)).build();
366         return network;
367     }
368
369
370
371
372     /*
373         getNaptSwitchesDpnIdsfromRouterId() returns the primary-switch-id and the secondary-switch-id in a array using the router-id; as the key.
374             container napt-switches {
375                 list router-to-napt-switch {
376                     key router-id;
377                     leaf router-id { type uint32; }
378                     leaf primary-switch-id { type uint64; }
379                     leaf secondary-switch-id { type uint64; }
380                 }
381             }
382     */
383     public static BigInteger getPrimaryNaptfromRouterId(DataBroker broker, Long routerId) {
384         // convert routerId to Name
385         String routerName = getRouterName(broker, routerId);
386         InstanceIdentifier id = buildNaptSwitchIdentifier(routerName);
387         Optional<RouterToNaptSwitch> routerToNaptSwitchData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
388         if (routerToNaptSwitchData.isPresent()) {
389             RouterToNaptSwitch routerToNaptSwitchInstance = routerToNaptSwitchData.get();
390             return routerToNaptSwitchInstance.getPrimarySwitchId();
391         }
392         return null;
393     }
394
395     private static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchIdentifier(String routerId) {
396         InstanceIdentifier<RouterToNaptSwitch> rtrNaptSw = InstanceIdentifier.builder(NaptSwitches.class).child
397                 (RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerId)).build();
398         return rtrNaptSw;
399     }
400
401     public static String getRouterName(DataBroker broker, Long routerId) {
402         InstanceIdentifier id = buildRouterIdentifier(routerId);
403         Optional<RouterIds> routerIdsData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
404         if (routerIdsData.isPresent()) {
405             RouterIds routerIdsInstance = routerIdsData.get();
406             return routerIdsInstance.getRouterName();
407         }
408         return null;
409     }
410
411     private static InstanceIdentifier<RouterIds> buildRouterIdentifier(Long routerId) {
412         InstanceIdentifier<RouterIds> routerIds = InstanceIdentifier.builder(RouterIdName.class).child
413                 (RouterIds.class, new RouterIdsKey(routerId)).build();
414         return routerIds;
415     }
416
417     public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
418                                                           InstanceIdentifier<T> path) {
419
420         ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
421
422         Optional<T> result = Optional.absent();
423         try {
424             result = tx.read(datastoreType, path).get();
425         } catch (Exception e) {
426             throw new RuntimeException(e);
427         }
428
429         return result;
430     }
431
432     static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String vrfId) {
433         return InstanceIdentifier.builder(VpnInstanceOpData.class)
434                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vrfId)).build();
435     }
436
437     public static long readVpnId(DataBroker broker, String vpnName) {
438
439         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
440                 = getVpnInstanceToVpnIdIdentifier(vpnName);
441         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
442                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
443
444         long vpnId = NatConstants.INVALID_ID;
445         if(vpnInstance.isPresent()) {
446             vpnId = vpnInstance.get().getVpnId();
447         }
448         return vpnId;
449     }
450
451     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, BigInteger cookie) {
452         FlowEntity flowEntity = new FlowEntity(dpnId);
453         flowEntity.setTableId(tableId);
454         flowEntity.setCookie(cookie);
455         return flowEntity;
456     }
457
458     public static long getIpAddress(byte[] rawIpAddress) {
459         return (((rawIpAddress[0] & 0xFF) << (3 * 8)) + ((rawIpAddress[1] & 0xFF) << (2 * 8))
460                 + ((rawIpAddress[2] & 0xFF) << (1 * 8)) + (rawIpAddress[3] & 0xFF)) & 0xffffffffL;
461     }
462
463     public static String getFlowRef(BigInteger dpnId, short tableId, InetAddress destPrefix) {
464         return new StringBuilder(64).append(NatConstants.FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
465                 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
466                 .append(destPrefix.getHostAddress()).toString();
467     }
468
469     public static String getEndpointIpAddressForDPN(DataBroker broker, BigInteger dpnId) {
470         String nextHopIp = null;
471         InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
472                 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpnId)).build();
473         Optional<DPNTEPsInfo> tunnelInfo = read(broker, LogicalDatastoreType.CONFIGURATION, tunnelInfoId);
474         if (tunnelInfo.isPresent()) {
475             List<TunnelEndPoints> nexthopIpList = tunnelInfo.get().getTunnelEndPoints();
476             if (nexthopIpList != null && !nexthopIpList.isEmpty()) {
477                 nextHopIp = nexthopIpList.get(0).getIpAddress().getIpv4Address().getValue();
478             }
479         }
480         return nextHopIp;
481     }
482
483     /*
484         getVpnRd returns the rd (route distinguisher) which is the VRF ID from the below model using the vpnName
485             list vpn-instance {
486                 key "vpn-instance-name"
487                 leaf vpn-instance-name {
488                     type string;
489                 }
490                 leaf vpn-id {
491                     type uint32;
492                 }
493                 leaf vrf-id {
494                     type string;
495                 }
496             }
497     */
498     public static String getVpnRd(DataBroker broker, String vpnName) {
499
500         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
501                 = getVpnInstanceToVpnIdIdentifier(vpnName);
502         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
503                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
504
505         String rd = null;
506         if(vpnInstance.isPresent()) {
507             rd = vpnInstance.get().getVrfId();
508         }
509         return rd;
510     }
511
512     /*  getExternalIPPortMap() returns the internal IP and the port for the querried router ID, external IP and the port.
513         container intext-ip-port-map {
514         config true;
515         list ip-port-mapping {
516             key router-id;
517             leaf router-id { type uint32; }
518             list intext-ip-protocol-type {
519                 key protocol;
520                 leaf protocol { type protocol-types; }
521                 list ip-port-map {
522                     key ip-port-internal;
523                     description "internal to external ip-port mapping";
524                     leaf ip-port-internal { type string; }
525                     container ip-port-external {
526                        uses ip-port-entity;
527                     }
528                 }
529             }
530          }
531        }
532     */
533     public static IpPortExternal getExternalIpPortMap(DataBroker broker, Long routerId, String internalIpAddress, String internalPort, NAPTEntryEvent.Protocol protocol) {
534         ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
535         InstanceIdentifier ipPortMapId = buildIpToPortMapIdentifier(routerId, internalIpAddress, internalPort, protocolType);
536         Optional<IpPortMap> ipPortMapData = read(broker, LogicalDatastoreType.CONFIGURATION, ipPortMapId);
537         if (ipPortMapData.isPresent()) {
538             IpPortMap ipPortMapInstance = ipPortMapData.get();
539             return ipPortMapInstance.getIpPortExternal();
540         }
541         return null;
542     }
543
544     private static InstanceIdentifier<IpPortMap> buildIpToPortMapIdentifier(Long routerId, String internalIpAddress, String internalPort , ProtocolTypes protocolType) {
545         InstanceIdentifier<IpPortMap> ipPortMapId = InstanceIdentifier.builder(IntextIpPortMap.class).child
546                 (IpPortMapping.class, new IpPortMappingKey(routerId)).child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
547                 .child(IpPortMap.class, new IpPortMapKey(internalIpAddress + ":" + internalPort)).build();
548         return ipPortMapId;
549     }
550
551     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId, int priority, String flowName,
552                                              BigInteger cookie, List<MatchInfo> listMatchInfo) {
553
554         FlowEntity flowEntity = new FlowEntity(dpnId);
555         flowEntity.setTableId(tableId);
556         flowEntity.setFlowId(flowId);
557         flowEntity.setPriority(priority);
558         flowEntity.setFlowName(flowName);
559         flowEntity.setCookie(cookie);
560         flowEntity.setMatchInfoList(listMatchInfo);
561         return flowEntity;
562     }
563
564     static boolean isVpnInterfaceConfigured(DataBroker broker, String interfaceName)
565     {
566         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
567         Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
568
569         if (configuredVpnInterface.isPresent()) {
570             return true;
571         }
572         return false;
573     }
574
575     static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
576         return InstanceIdentifier.builder(VpnInterfaces.class)
577                 .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build();
578     }
579
580     static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
581         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
582         Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
583
584         if (configuredVpnInterface.isPresent()) {
585             return configuredVpnInterface.get();
586         }
587         return null;
588     }
589
590     public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
591         /*
592          * NodeConnectorId is of form 'openflow:dpnid:portnum'
593          */
594         String[] split = portId.getValue().split(OF_URI_SEPARATOR);
595         return split[1];
596     }
597
598     public static BigInteger getDpIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
599         String lowerLayerIf = ifState.getLowerLayerIf().get(0);
600         NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
601         return new BigInteger(getDpnFromNodeConnectorId(nodeConnectorId));
602     }
603
604
605     /*
606     container vpnMaps {
607         list vpnMap {
608             key vpn-id;
609             leaf vpn-id {
610                 type    yang:uuid;
611                 description "vpn-id";
612             }
613             leaf name {
614                 type  string;
615                 description "vpn name";
616             }
617             leaf tenant-id {
618                 type    yang:uuid;
619                 description "The UUID of the tenant that will own the subnet.";
620             }
621
622             leaf router-id {
623               type    yang:uuid;
624               description "UUID of router ";
625             }
626             leaf-list network_ids {
627               type    yang:uuid;
628               description "UUID representing the network ";
629             }
630         }
631     }
632     Method returns router Id associated to a VPN
633      */
634
635     public static String getRouterIdfromVpnInstance(DataBroker broker,String vpnName){
636         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
637                 .child(VpnMap.class, new VpnMapKey(new Uuid(vpnName))).build();
638         Optional<VpnMap> optionalVpnMap = read(broker, LogicalDatastoreType.CONFIGURATION,
639                 vpnMapIdentifier);
640         if (optionalVpnMap.isPresent()) {
641             return optionalVpnMap.get().getRouterId().getValue();
642         }
643         return null;
644     }
645
646     public static String getRouterIdfromVpnId(DataBroker broker, long vpnId){
647         String vpnName = getVpnInstanceFromVpnIdentifier(broker, vpnId);
648         if (vpnName == null) {
649             LOG.trace("No VPN instance found for vpn id {}", vpnId);
650             return null;
651         }
652
653         return getRouterIdfromVpnInstance(broker, vpnName);
654     }
655
656     static Uuid getVpnForRouter(DataBroker broker, String routerId) {
657         InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
658         Optional<VpnMaps> optionalVpnMaps = read(broker, LogicalDatastoreType.CONFIGURATION,
659                 vpnMapsIdentifier);
660         if (optionalVpnMaps.isPresent() && optionalVpnMaps.get().getVpnMap() != null) {
661             List<VpnMap> allMaps = optionalVpnMaps.get().getVpnMap();
662             if (routerId != null) {
663                 for (VpnMap vpnMap : allMaps) {
664                     if (vpnMap.getRouterId() != null &&
665                             routerId.equals(vpnMap.getRouterId().getValue()) &&
666                             !routerId.equals(vpnMap.getVpnId().getValue())) {
667                         return vpnMap.getVpnId();
668                     }
669                 }
670             }
671         }
672         return null;
673     }
674
675     static long getAssociatedVpn(DataBroker broker, String routerName) {
676         InstanceIdentifier<Routermapping> routerMappingId = NatUtil.getRouterVpnMappingId(routerName);
677         Optional<Routermapping> optRouterMapping = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, routerMappingId);
678         if(optRouterMapping.isPresent()) {
679             Routermapping routerMapping = optRouterMapping.get();
680             return routerMapping.getVpnId();
681         }
682         return NatConstants.INVALID_ID;
683     }
684
685
686     public static List<VpnToDpnList> getVpnToDpnList(DataBroker dataBroker, String vrfId )
687     {
688         List<VpnToDpnList> vpnDpnList = null;
689
690         InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier
691                 .builder(VpnInstanceOpData.class)
692                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vrfId))
693                 .build();
694
695         Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
696
697         if(vpnInstanceOpData.isPresent())
698         {
699             VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnInstanceOpData.get();
700             vpnDpnList = vpnInstanceOpDataEntry.getVpnToDpnList();
701         }
702
703         return vpnDpnList;
704     }
705
706     public static String getAssociatedVPN(DataBroker dataBroker, Uuid networkId, Logger log) {
707         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
708         if(vpnUuid == null ){
709             log.error("No VPN instance associated with ext network {}", networkId);
710             return null;
711         }
712         return vpnUuid.getValue();
713     }
714
715     public static void addPrefixToBGP(DataBroker broker,
716                                       IBgpManager bgpManager,
717                                       IFibManager fibManager,
718                                       String rd,
719                                       String prefix,
720                                       String nextHopIp,
721                                       long label,
722                                       Logger log,
723                                       RouteOrigin origin) {
724         try {
725             LOG.info("ADD: Adding Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
726             fibManager.addOrUpdateFibEntry(broker, rd, prefix, Arrays.asList(nextHopIp), (int)label, origin, null);
727             bgpManager.advertisePrefix(rd, prefix, Arrays.asList(nextHopIp), (int)label);
728             LOG.info("ADD: Added Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
729         } catch(Exception e) {
730             log.error("Add prefix failed", e);
731         }
732     }
733
734     static InstanceIdentifier<Ports> buildPortToIpMapIdentifier(String routerId, String portName) {
735         InstanceIdentifier<Ports> ipPortMapId = InstanceIdentifier.builder(FloatingIpInfo.class).child
736                 (RouterPorts.class, new RouterPortsKey(routerId)).child(Ports.class, new PortsKey(portName)).build();
737         return ipPortMapId;
738     }
739
740     static InstanceIdentifier<RouterPorts> buildRouterPortsIdentifier(String routerId) {
741         InstanceIdentifier<RouterPorts> routerInstanceIndentifier = InstanceIdentifier.builder(FloatingIpInfo.class).child
742                 (RouterPorts.class, new RouterPortsKey(routerId)).build();
743         return routerInstanceIndentifier;
744     }
745
746     /* container snatint-ip-port-map {
747         list intip-port-map {
748             key router-id;
749             leaf router-id { type uint32; }
750             list ip-port {
751                 key internal-ip;
752                 leaf internal-ip { type string; }
753                 list int-ip-proto-type {
754                     key protocol;
755                     leaf protocol { type protocol-types; }
756                     leaf-list ports { type uint16; }
757                 }
758             }
759         }
760     }
761     Method returns InternalIp port List
762     */
763
764     public static List<Integer> getInternalIpPortListInfo(DataBroker dataBroker,Long routerId, String internalIpAddress, ProtocolTypes protocolType){
765         Optional<IntIpProtoType> optionalIpProtoType = read(dataBroker, LogicalDatastoreType.CONFIGURATION, buildSnatIntIpPortIdentifier(routerId, internalIpAddress, protocolType));
766         if (optionalIpProtoType.isPresent()) {
767             return optionalIpProtoType.get().getPorts();
768         }
769         return null;
770     }
771
772     public static InstanceIdentifier<IntIpProtoType> buildSnatIntIpPortIdentifier(Long routerId, String internalIpAddress, ProtocolTypes protocolType) {
773         InstanceIdentifier<IntIpProtoType> intIpProtocolTypeId = InstanceIdentifier.builder(SnatintIpPortMap.class).child
774                 (IntipPortMap.class, new IntipPortMapKey(routerId)).child(IpPort.class, new IpPortKey(internalIpAddress)).child
775                 (IntIpProtoType.class, new IntIpProtoTypeKey(protocolType)).build();
776         return intIpProtocolTypeId;
777     }
778
779     public static ProtocolTypes getProtocolType(NAPTEntryEvent.Protocol protocol) {
780         ProtocolTypes protocolType = ProtocolTypes.TCP.toString().equals(protocol.toString()) ? ProtocolTypes.TCP : ProtocolTypes.UDP;
781         return protocolType;
782     }
783
784     public static NaptSwitches getNaptSwitch(DataBroker broker) {
785         Optional<NaptSwitches> switchesOptional = read(broker, LogicalDatastoreType.CONFIGURATION, getNaptSwitchesIdentifier());
786         if(switchesOptional.isPresent()) {
787             return switchesOptional.get();
788         }
789         return null;
790     }
791
792     public static InstanceIdentifier<NaptSwitches> getNaptSwitchesIdentifier() {
793         return InstanceIdentifier.create(NaptSwitches.class);
794     }
795
796     public static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchRouterIdentifier(String routerId) {
797         return InstanceIdentifier.create(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerId));
798     }
799
800     public static String toStringIpAddress(byte[] ipAddress, Logger log)
801     {
802         String ip = "";
803         if (ipAddress == null) {
804             return ip;
805         }
806
807         try {
808             ip = InetAddress.getByAddress(ipAddress).getHostAddress();
809         } catch(UnknownHostException e) {
810             log.error("NAT Service : Caught exception during toStringIpAddress()");
811         }
812
813         return ip;
814     }
815
816     public static String getGroupIdKey(String routerName){
817         String groupIdKey = new String("snatmiss." + routerName);
818         return groupIdKey;
819     }
820
821     public static long createGroupId(String groupIdKey,IdManagerService idManager) {
822         AllocateIdInput getIdInput = new AllocateIdInputBuilder()
823                 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
824                 .build();
825         try {
826             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
827             RpcResult<AllocateIdOutput> rpcResult = result.get();
828             return rpcResult.getResult().getIdValue();
829         } catch (NullPointerException | InterruptedException | ExecutionException e) {
830             LOG.trace("", e);
831         }
832         return 0;
833     }
834
835     public static void removePrefixFromBGP(DataBroker broker , IBgpManager bgpManager, IFibManager fibManager, String rd, String prefix, Logger log) {
836         try {
837             LOG.info("REMOVE: Removing Fib entry rd {} prefix {}", rd, prefix);
838             fibManager.removeFibEntry(broker, rd, prefix, null);
839             bgpManager.withdrawPrefix(rd, prefix);
840             LOG.info("REMOVE: Removed Fib entry rd {} prefix {}", rd, prefix);
841         } catch(Exception e) {
842             log.error("Delete prefix failed", e);
843         }
844     }
845
846     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, BigInteger cookie, String flowId) {
847         FlowEntity flowEntity = new FlowEntity(dpnId);
848         flowEntity.setTableId(tableId);
849         flowEntity.setCookie(cookie);
850         flowEntity.setFlowId(flowId);
851         return flowEntity;
852     }
853
854     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId) {
855         FlowEntity flowEntity = new FlowEntity(dpnId);
856         flowEntity.setTableId(tableId);
857         flowEntity.setFlowId(flowId);
858         return flowEntity;
859     }
860
861     public static IpPortMapping getIportMapping(DataBroker broker, long routerId) {
862         Optional<IpPortMapping> getIportMappingData = read(broker, LogicalDatastoreType.CONFIGURATION, getIportMappingIdentifier(routerId));
863         if(getIportMappingData.isPresent()) {
864             return getIportMappingData.get();
865         }
866         return null;
867     }
868
869     public static InstanceIdentifier<IpPortMapping> getIportMappingIdentifier(long routerId) {
870         return InstanceIdentifier.builder(IntextIpPortMap.class).child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
871     }
872
873     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping> getIpMappingBuilder(Long routerId) {
874         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
875                 .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();
876         return idBuilder;
877     }
878
879     public static List<String> getExternalIpsForRouter(DataBroker dataBroker,Long routerId) {
880         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping> ipMappingOptional = read(dataBroker,
881                 LogicalDatastoreType.OPERATIONAL, getIpMappingBuilder(routerId));
882         List<String> externalIps = new ArrayList<>();
883         if (ipMappingOptional.isPresent()) {
884             List<IpMap> ipMaps = ipMappingOptional.get().getIpMap();
885             for (IpMap ipMap : ipMaps) {
886                 externalIps.add(ipMap.getExternalIp());
887             }
888             //remove duplicates
889             Set<String> uniqueExternalIps = Sets.newHashSet(externalIps);
890             externalIps = Lists.newArrayList(uniqueExternalIps);
891             return externalIps;
892         }
893         return null;
894     }
895
896     public static HashMap<String,Long> getExternalIpsLabelForRouter(DataBroker dataBroker,Long routerId) {
897         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.map.IpMapping> ipMappingOptional = read(dataBroker,
898                 LogicalDatastoreType.OPERATIONAL, getIpMappingBuilder(routerId));
899         HashMap<String,Long> externalIpsLabel = new HashMap<>();
900         if (ipMappingOptional.isPresent()) {
901             List<IpMap> ipMaps = ipMappingOptional.get().getIpMap();
902             for (IpMap ipMap : ipMaps) {
903                 externalIpsLabel.put(ipMap.getExternalIp(), ipMap.getLabel());
904             }
905             return externalIpsLabel;
906         }
907         return null;
908     }
909     /*
910     container external-ips-counter {
911         config false;
912         list external-counters{
913             key segment-id;
914             leaf segment-id { type uint32; }
915             list external-ip-counter {
916                 key external-ip;
917                 leaf external-ip { type string; }
918                 leaf counter { type uint8; }
919             }
920         }
921     }
922     */
923
924     public static String getLeastLoadedExternalIp(DataBroker dataBroker, long segmentId){
925         String leastLoadedExternalIp =  null;
926         InstanceIdentifier<ExternalCounters> id = InstanceIdentifier.builder(ExternalIpsCounter.class).child(ExternalCounters.class, new ExternalCountersKey(segmentId)).build();
927         Optional <ExternalCounters> externalCountersData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
928         if (externalCountersData.isPresent()) {
929             ExternalCounters externalCounter = externalCountersData.get();
930             List<ExternalIpCounter> externalIpCounterList = externalCounter.getExternalIpCounter();
931             short countOfLstLoadExtIp = 32767;
932             for(ExternalIpCounter externalIpCounter : externalIpCounterList){
933                 String curExternalIp = externalIpCounter.getExternalIp();
934                 short countOfCurExtIp  = externalIpCounter.getCounter();
935                 if( countOfCurExtIp < countOfLstLoadExtIp ){
936                     countOfLstLoadExtIp = countOfCurExtIp;
937                     leastLoadedExternalIp = curExternalIp;
938                 }
939             }
940         }
941         return leastLoadedExternalIp;
942     }
943
944     public static String[] getSubnetIpAndPrefix(DataBroker dataBroker, Uuid subnetId){
945         String subnetIP = getSubnetIp(dataBroker, subnetId);
946         if(subnetId != null){
947             return getSubnetIpAndPrefix(subnetIP);
948         }
949         return null;
950     }
951
952     public static String getSubnetIp(DataBroker dataBroker, Uuid subnetId){
953         InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
954                 .builder(Subnetmaps.class)
955                 .child(Subnetmap.class, new SubnetmapKey(subnetId))
956                 .build();
957         Optional<Subnetmap> removedSubnet = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
958         if(removedSubnet.isPresent()) {
959             Subnetmap subnetMapEntry = removedSubnet.get();
960             return subnetMapEntry.getSubnetIp();
961         }
962         return null;
963
964     }
965     public static String[] getSubnetIpAndPrefix(String subnetString){
966         String[] subnetSplit = subnetString.split("/");
967         String subnetIp = subnetSplit[0];
968         String subnetPrefix = "0";
969         if (subnetSplit.length == 2) {
970             subnetPrefix = subnetSplit[1];
971         }
972         return new String[] {subnetIp, subnetPrefix};
973     }
974
975     public static String[] getExternalIpAndPrefix(String leastLoadedExtIpAddr){
976         String[] leastLoadedExtIpAddrSplit = leastLoadedExtIpAddr.split("/");
977         String leastLoadedExtIp = leastLoadedExtIpAddrSplit[0];
978         String leastLoadedExtIpPrefix = String.valueOf(NatConstants.DEFAULT_PREFIX);
979         if (leastLoadedExtIpAddrSplit.length == 2) {
980             leastLoadedExtIpPrefix = leastLoadedExtIpAddrSplit[1];
981         }
982         return new String[] {leastLoadedExtIp, leastLoadedExtIpPrefix};
983     }
984
985     public static List<BigInteger> getDpnsForRouter(DataBroker dataBroker, String routerUuid){
986         InstanceIdentifier id = InstanceIdentifier.builder(NeutronRouterDpns.class).child(RouterDpnList.class, new RouterDpnListKey(routerUuid)).build();
987         Optional<RouterDpnList> routerDpnListData = read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
988         List<BigInteger> dpns = new ArrayList<>();
989         if (routerDpnListData.isPresent()) {
990             List<DpnVpninterfacesList> dpnVpninterfacesList = routerDpnListData.get().getDpnVpninterfacesList();
991             for (DpnVpninterfacesList dpnVpnInterface : dpnVpninterfacesList) {
992                 dpns.add(dpnVpnInterface.getDpnId());
993             }
994             return dpns;
995         }
996         return null;
997     }
998
999     public static long getBgpVpnId(DataBroker dataBroker, String routerName){
1000         long bgpVpnId = NatConstants.INVALID_ID;
1001         Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
1002         if(bgpVpnUuid != null){
1003             bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
1004         }
1005         return bgpVpnId;
1006     }
1007
1008     public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
1009         BigInteger nodeId = BigInteger.ZERO;
1010         try {
1011             GetDpidFromInterfaceInput
1012                     dpIdInput =
1013                     new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
1014             Future<RpcResult<GetDpidFromInterfaceOutput>>
1015                     dpIdOutput =
1016                     interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
1017             RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
1018             if (dpIdResult.isSuccessful()) {
1019                 nodeId = dpIdResult.getResult().getDpid();
1020             } else {
1021                 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
1022             }
1023         } catch (InterruptedException | ExecutionException e) {
1024             LOG.error("Exception when getting dpn for interface {}", ifName,  e);
1025         }
1026         return nodeId;
1027     }
1028
1029     public static List<ActionInfo> getEgressActionsForInterface(OdlInterfaceRpcService interfaceManager, String ifName,
1030             Long tunnelKey) {
1031         return getEgressActionsForInterface(interfaceManager, ifName, tunnelKey, 0);
1032     }
1033
1034     public static List<ActionInfo> getEgressActionsForInterface(OdlInterfaceRpcService interfaceManager, String ifName,
1035             Long tunnelKey, int pos) {
1036         LOG.debug("NAT Service : getEgressActionsForInterface called for interface {}", ifName);
1037         GetEgressActionsForInterfaceInputBuilder egressActionsBuilder = new GetEgressActionsForInterfaceInputBuilder()
1038                 .setIntfName(ifName);
1039         if (tunnelKey != null) {
1040             egressActionsBuilder.setTunnelKey(tunnelKey);
1041         }
1042
1043         List<ActionInfo> listActionInfo = new ArrayList<>();
1044         try {
1045             Future<RpcResult<GetEgressActionsForInterfaceOutput>> result = interfaceManager
1046                     .getEgressActionsForInterface(egressActionsBuilder.build());
1047             RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
1048             if (!rpcResult.isSuccessful()) {
1049                 LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName,
1050                         rpcResult.getErrors());
1051             } else {
1052                 List<Action> actions = rpcResult.getResult().getAction();
1053                 for (Action action : actions) {
1054                     org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionClass = action
1055                             .getAction();
1056                     if (actionClass instanceof OutputActionCase) {
1057                         listActionInfo
1058                                 .add(new ActionInfo(ActionType.output, new String[] { ((OutputActionCase) actionClass)
1059                                         .getOutputAction().getOutputNodeConnector().getValue() }, pos++));
1060                     } else if (actionClass instanceof PushVlanActionCase) {
1061                         listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {}, pos++));
1062                     } else if (actionClass instanceof SetFieldCase) {
1063                         if (((SetFieldCase) actionClass).getSetField().getVlanMatch() != null) {
1064                             int vlanVid = ((SetFieldCase) actionClass).getSetField().getVlanMatch().getVlanId()
1065                                     .getVlanId().getValue();
1066                             listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid,
1067                                     new String[] { Long.toString(vlanVid) }, pos++));
1068                         }
1069                     } else if (actionClass instanceof NxActionResubmitRpcAddGroupCase) {
1070                         Short tableId = ((NxActionResubmitRpcAddGroupCase)actionClass).getNxResubmit().getTable();
1071                         listActionInfo.add(new ActionInfo(ActionType.nx_resubmit,
1072                             new String[] { tableId.toString() }, pos++));
1073                     } else if (actionClass instanceof NxActionRegLoadNodesNodeTableFlowApplyActionsCase) {
1074                         NxRegLoad nxRegLoad =
1075                             ((NxActionRegLoadNodesNodeTableFlowApplyActionsCase)actionClass).getNxRegLoad();
1076                         listActionInfo.add(new ActionInfo(ActionType.nx_load_reg_6,
1077                             new String[] { nxRegLoad.getDst().getStart().toString(),
1078                                 nxRegLoad.getDst().getEnd().toString(),
1079                                 nxRegLoad.getValue().toString(10)}, pos++));
1080                     }
1081                 }
1082             }
1083         } catch (InterruptedException | ExecutionException e) {
1084             LOG.warn("Exception when egress actions for interface {}", ifName, e);
1085         }
1086         return listActionInfo;
1087     }
1088
1089     public static Port getNeutronPortForFloatingIp(DataBroker broker,
1090         IpAddress targetIP) {
1091         return getNeutronPortForIp(broker, targetIP, NeutronConstants.DEVICE_OWNER_FLOATING_IP);
1092     }
1093
1094     public static Port getNeutronPortForRouterGetewayIp(DataBroker broker,
1095         IpAddress targetIP) {
1096         return getNeutronPortForIp(broker, targetIP, NeutronConstants.DEVICE_OWNER_GATEWAY_INF);
1097     }
1098
1099     public static Port getNeutronPortForIp(DataBroker broker,
1100         IpAddress targetIP, String deviceType) {
1101         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports>
1102         portsIdentifier = InstanceIdentifier
1103                 .create(Neutron.class)
1104                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports.class);
1105         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports> portsOptional = read(
1106                 broker, LogicalDatastoreType.CONFIGURATION, portsIdentifier);
1107         if (!portsOptional.isPresent() || portsOptional.get().getPort() == null) {
1108             LOG.trace("No neutron ports found");
1109             return null;
1110         }
1111
1112         for (Port port : portsOptional.get().getPort()) {
1113             if (deviceType.equals(port.getDeviceOwner()) && port.getFixedIps() != null) {
1114                 for (FixedIps ip : port.getFixedIps()) {
1115                     if (Objects.equals(ip.getIpAddress(), targetIP)) {
1116                         return port;
1117                     }
1118                 }
1119             }
1120         }
1121
1122         return null;
1123     }
1124
1125     public static Uuid getSubnetIdForFloatingIp(Port port,
1126             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress targetIP) {
1127         if (port == null) {
1128             return null;
1129         }
1130
1131         for (FixedIps ip : port.getFixedIps()) {
1132             if (Objects.equals(ip.getIpAddress(), targetIP)) {
1133                 return ip.getSubnetId();
1134             }
1135         }
1136
1137         return null;
1138     }
1139
1140     public static Subnetmap getSubnetMap(DataBroker broker, Uuid subnetId) {
1141         InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier.builder(Subnetmaps.class)
1142                 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
1143         Optional<Subnetmap> subnetOpt = read(broker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
1144         return subnetOpt.isPresent() ? subnetOpt.get() : null;
1145     }
1146
1147     public static String getSubnetGwMac(DataBroker broker, Uuid subnetId, String vpnName) {
1148         if (subnetId == null) {
1149             return null;
1150         }
1151
1152         InstanceIdentifier<Subnet> subnetInst = InstanceIdentifier.create(Neutron.class).child(Subnets.class)
1153                 .child(Subnet.class, new SubnetKey(subnetId));
1154         Optional<Subnet> subnetOpt = read(broker, LogicalDatastoreType.CONFIGURATION, subnetInst);
1155         if (!subnetOpt.isPresent()) {
1156             return null;
1157         }
1158
1159         IpAddress gatewayIp = subnetOpt.get().getGatewayIp();
1160         if (gatewayIp == null) {
1161             LOG.trace("No GW ip found for subnet {}", subnetId.getValue());
1162             return null;
1163         }
1164
1165         InstanceIdentifier<VpnPortipToPort> portIpInst = InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
1166                 .child(VpnPortipToPort.class, new VpnPortipToPortKey(gatewayIp.getIpv4Address().getValue(), vpnName))
1167                 .build();
1168         Optional<VpnPortipToPort> portIpToPortOpt = read(broker, LogicalDatastoreType.OPERATIONAL, portIpInst);
1169         if (!portIpToPortOpt.isPresent()) {
1170             LOG.trace("No resolution was found to GW ip {} in subnet {}", gatewayIp, subnetId.getValue());
1171             return null;
1172         }
1173
1174         return portIpToPortOpt.get().getMacAddress();
1175     }
1176 }