166bb7226562f709c508b3d8c638142b8ad5efbb
[vpnservice.git] / natservice / natservice-impl / src / main / java / org / opendaylight / vpnservice / 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.vpnservice.natservice.internal;
10
11 import java.math.BigInteger;
12 import java.util.List;
13
14 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
15 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
16 import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
17 import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
18 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
19 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
20 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
21 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceToVpnId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.*;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.Routers;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.RoutersKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolTypeKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.id.name.RouterIds;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.id.name.RouterIdsKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.IntipPortMap;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.IntipPortMapKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPortKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.FloatingIpInfo;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.VpnMaps;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMap;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMapKey;
49 import org.opendaylight.yangtools.yang.binding.DataObject;
50 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
52 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
53
54 import com.google.common.base.Optional;
55 import org.opendaylight.bgpmanager.api.IBgpManager;
56 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.Networks;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.NetworksKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPorts;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPortsKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.Ports;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.PortsKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExternalNetworks;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.DpnEndpoints;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfoKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMappingKey;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.IntextIpPortMap;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMapping;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
78 import org.opendaylight.yangtools.yang.common.RpcResult;
79 import org.slf4j.Logger;
80 import org.slf4j.LoggerFactory;
81
82 import java.net.InetAddress;
83 import java.net.UnknownHostException;
84 import java.util.concurrent.ExecutionException;
85 import java.util.concurrent.Future;
86
87
88
89 public class NatUtil {
90
91     private static String OF_URI_SEPARATOR = ":";
92     private static final Logger LOG = LoggerFactory.getLogger(NatUtil.class);
93
94     /*
95         getCookieSnatFlow() computes and returns a unique cookie value for the NAT flows using the router ID as the reference value.
96      */
97     public static BigInteger getCookieSnatFlow(long routerId) {
98         return NatConstants.COOKIE_NAPT_BASE.add(new BigInteger("0110000", 16)).add(
99                 BigInteger.valueOf(routerId));
100     }
101
102     /*
103         getCookieNaptFlow() computes and returns a unique cookie value for the NAPT flows using the router ID as the reference value.
104     */
105     public static BigInteger getCookieNaptFlow(long routerId) {
106         return NatConstants.COOKIE_NAPT_BASE.add(new BigInteger("0111000", 16)).add(
107                 BigInteger.valueOf(routerId));
108     }
109
110     /*
111         getVpnId() returns the VPN ID from the VPN name
112      */
113     public static long getVpnId(DataBroker broker, String vpnName) {
114
115         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
116                 = getVpnInstanceToVpnIdIdentifier(vpnName);
117         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
118                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
119
120         long vpnId = NatConstants.INVALID_ID;
121         if(vpnInstance.isPresent()) {
122             vpnId = vpnInstance.get().getVpnId();
123         }
124         return vpnId;
125     }
126         
127     static InstanceIdentifier<RouterPorts> getRouterPortsId(String routerId) {
128         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId)).build();
129     }
130     
131     static InstanceIdentifier<Ports> getPortsIdentifier(String routerId, String portName) {
132         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId))
133                                                                .child(Ports.class, new PortsKey(portName)).build();
134     }
135  
136
137     static InstanceIdentifier<IpMapping> getIpMappingIdentifier(String routerId, String portName, String internalIp) {
138         return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId))
139                                                                .child(Ports.class, new PortsKey(portName))
140                                                                .child(IpMapping.class, new IpMappingKey(internalIp)).build();
141     }
142
143     /*
144         getVpnInstanceToVpnIdIdentifier() returns the VPN instance from the below model using the VPN name as the key.
145             list vpn-instance {
146                 key "vpn-instance-name"
147                 leaf vpn-instance-name {
148                     type string;
149                 }
150                 leaf vpn-id {
151                     type uint32;
152                 }
153                 leaf vrf-id {
154                     type string;
155                 }
156             }
157     */
158
159     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
160     getVpnInstanceToVpnIdIdentifier(String vpnName) {
161         return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
162                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
163                         new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
164     }
165
166      /*
167         getFlowRef() returns a string identfier for the SNAT flows using the router ID as the reference.
168      */
169     public static String getFlowRef(BigInteger dpnId, short tableId, String routerID) {
170         return new StringBuffer().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
171                 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
172     }
173
174     public static String getNaptFlowRef(BigInteger dpnId, short tableId, String routerID, String ip, int port) {
175         return new StringBuffer().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
176                 append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).append(NatConstants.FLOWID_SEPARATOR).append(ip).
177                 append(NatConstants.FLOWID_SEPARATOR).append(port).toString();
178     }
179
180     /*
181         getNetworkIdFromRouterId() returns the network-id from the below model using the router-id as the key
182                container ext-routers {
183                    list routers {
184                        key router-name;
185                        leaf router-name { type string; }
186                        leaf network-id { type yang:uuid; }
187                        leaf enable-snat { type boolean; }
188                        leaf-list external-ips {
189                             type string; //format - ipaddress\prefixlength
190                        }
191                        leaf-list subnet-ids { type yang:uuid; }
192                    }
193                }
194
195     */
196     static Uuid getNetworkIdFromRouterId(DataBroker broker, long routerId) {
197         String routerName = getRouterName(broker, routerId);
198         InstanceIdentifier id = buildRouterIdentifier(routerName);
199         Optional<Routers> routerData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
200         if (routerData.isPresent()) {
201             return routerData.get().getNetworkId();
202         }
203         return null;
204     }
205
206     static InstanceIdentifier<Routers> buildRouterIdentifier(String routerId) {
207         InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
208                 (Routers.class, new RoutersKey(routerId)).build();
209         return routerInstanceIndentifier;
210     }
211     /*
212      * getEnableSnatFromRouterId() returns IsSnatEnabled true is routerID is present in external n/w otherwise returns false
213      */
214     static boolean isSnatEnabledForRouterId(DataBroker broker, String routerId){
215         InstanceIdentifier id = buildRouterIdentifier(routerId);
216         Optional<Routers> routerData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
217         if (routerData.isPresent()) {
218             return routerData.get().isEnableSnat();
219         }
220         return false;
221     }
222     /*
223         getVpnIdfromNetworkId() returns the vpnid from the below model using the network ID as the key.
224             container external-networks {
225                 list networks  {
226                     key id;
227                     leaf id {
228                         type yang:uuid;
229                     }
230                     leaf vpnid { type yang:uuid; }
231                     leaf-list router-ids { type yang:uuid; }
232                     leaf-list subnet-ids{ type yang:uuid; }
233                 }
234             }
235     */
236     public static Uuid getVpnIdfromNetworkId(DataBroker broker, Uuid networkId) {
237         InstanceIdentifier id = buildNetworkIdentifier(networkId);
238         Optional<Networks> networkData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
239         if (networkData.isPresent()) {
240             return networkData.get().getVpnid();
241         }
242         return null;
243     }
244
245     private static InstanceIdentifier<Networks> buildNetworkIdentifier(Uuid networkId) {
246         InstanceIdentifier<Networks> network = InstanceIdentifier.builder(ExternalNetworks.class).child
247                 (Networks.class, new NetworksKey(networkId)).build();
248         return network;
249     }
250
251
252
253     /*
254         getNaptSwitchesDpnIdsfromRouterId() returns the primary-switch-id and the secondary-switch-id in a array using the router-id; as the key.
255             container napt-switches {
256                 list router-to-napt-switch {
257                     key router-id;
258                     leaf router-id { type uint32; }
259                     leaf primary-switch-id { type uint64; }
260                     leaf secondary-switch-id { type uint64; }
261                 }
262             }
263     */
264     public static BigInteger getPrimaryNaptfromRouterId(DataBroker broker, Long routerId) {
265         // convert routerId to Name
266         String routerName = getRouterName(broker, routerId);
267         InstanceIdentifier id = buildNaptSwitchIdentifier(routerName);
268         Optional<RouterToNaptSwitch> routerToNaptSwitchData = read(broker, LogicalDatastoreType.OPERATIONAL, id);
269         if (routerToNaptSwitchData.isPresent()) {
270             RouterToNaptSwitch routerToNaptSwitchInstance = routerToNaptSwitchData.get();
271             return routerToNaptSwitchInstance.getPrimarySwitchId();
272         }
273         return null;
274     }
275
276     private static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchIdentifier(String routerId) {
277         InstanceIdentifier<RouterToNaptSwitch> rtrNaptSw = InstanceIdentifier.builder(NaptSwitches.class).child
278                 (RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerId)).build();
279         return rtrNaptSw;
280     }
281
282     public static String getRouterName(DataBroker broker, Long routerId) {
283         InstanceIdentifier id = buildRouterIdentifier(routerId);
284         Optional<RouterIds> routerIdsData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
285         if (routerIdsData.isPresent()) {
286             RouterIds routerIdsInstance = routerIdsData.get();
287             return routerIdsInstance.getRouterName();
288         }
289         return null;
290     }
291
292     private static InstanceIdentifier<RouterIds> buildRouterIdentifier(Long routerId) {
293         InstanceIdentifier<RouterIds> routerIds = InstanceIdentifier.builder(RouterIdName.class).child
294                 (RouterIds.class, new RouterIdsKey(routerId)).build();
295         return routerIds;
296     }
297
298     public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
299                                                    InstanceIdentifier<T> path) {
300
301         ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
302
303         Optional<T> result = Optional.absent();
304         try {
305             result = tx.read(datastoreType, path).get();
306         } catch (Exception e) {
307             throw new RuntimeException(e);
308         }
309
310         return result;
311     }
312
313     static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String vrfId) {
314         return InstanceIdentifier.builder(VpnInstanceOpData.class)
315                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vrfId)).build();
316     }
317
318     public static long readVpnId(DataBroker broker, String vpnName) {
319
320         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
321                 = getVpnInstanceToVpnIdIdentifier(vpnName);
322         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
323                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
324
325         long vpnId = NatConstants.INVALID_ID;
326         if(vpnInstance.isPresent()) {
327             vpnId = vpnInstance.get().getVpnId();
328         }
329         return vpnId;
330     }
331
332     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, BigInteger cookie) {
333         FlowEntity flowEntity = new FlowEntity(dpnId);
334         flowEntity.setTableId(tableId);
335         flowEntity.setCookie(cookie);
336         return flowEntity;
337     }
338
339     public static long getIpAddress(byte[] rawIpAddress) {
340         return (((rawIpAddress[0] & 0xFF) << (3 * 8)) + ((rawIpAddress[1] & 0xFF) << (2 * 8))
341                 + ((rawIpAddress[2] & 0xFF) << (1 * 8)) + (rawIpAddress[3] & 0xFF)) & 0xffffffffL;
342     }
343
344     public static String getFlowRef(BigInteger dpnId, short tableId, InetAddress destPrefix) {
345         return new StringBuilder(64).append(NatConstants.FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
346                 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
347                 .append(destPrefix.getHostAddress()).toString();
348     }
349
350     public static String getEndpointIpAddressForDPN(DataBroker broker, BigInteger dpnId) {
351         String nextHopIp = null;
352         InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
353             InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpnId)).build();
354         Optional<DPNTEPsInfo> tunnelInfo = read(broker, LogicalDatastoreType.CONFIGURATION, tunnelInfoId);
355         if (tunnelInfo.isPresent()) {
356           List<TunnelEndPoints> nexthopIpList = tunnelInfo.get().getTunnelEndPoints();
357           if (nexthopIpList != null && !nexthopIpList.isEmpty()) {
358             nextHopIp = nexthopIpList.get(0).getIpAddress().getIpv4Address().getValue();
359           }
360         }
361         return nextHopIp;
362       }
363
364     /*
365         getVpnRd returns the rd (route distinguisher) which is the VRF ID from the below model using the vpnName
366             list vpn-instance {
367                 key "vpn-instance-name"
368                 leaf vpn-instance-name {
369                     type string;
370                 }
371                 leaf vpn-id {
372                     type uint32;
373                 }
374                 leaf vrf-id {
375                     type string;
376                 }
377             }
378     */
379     public static String getVpnRd(DataBroker broker, String vpnName) {
380
381         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
382                 = getVpnInstanceToVpnIdIdentifier(vpnName);
383         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
384                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
385
386         String rd = null;
387         if(vpnInstance.isPresent()) {
388             rd = vpnInstance.get().getVrfId();
389         }
390         return rd;
391     }
392
393     /*  getExternalIPPortMap() returns the internal IP and the port for the querried router ID, external IP and the port.
394         container intext-ip-port-map {
395         config true;
396         list ip-port-mapping {
397             key router-id;
398             leaf router-id { type uint32; }
399             list intext-ip-protocol-type {
400                 key protocol;
401                 leaf protocol { type protocol-types; }
402                 list ip-port-map {
403                     key ip-port-internal;
404                     description "internal to external ip-port mapping";
405                     leaf ip-port-internal { type string; }
406                     container ip-port-external {
407                        uses ip-port-entity;
408                     }
409                 }
410             }
411          }
412        }
413     */
414     public static IpPortExternal getExternalIpPortMap(DataBroker broker, Long routerId, String internalIpAddress, String internalPort, NAPTEntryEvent.Protocol protocol) {
415         ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
416         InstanceIdentifier ipPortMapId = buildIpToPortMapIdentifier(routerId, internalIpAddress, internalPort, protocolType);
417         Optional<IpPortMap> ipPortMapData = read(broker, LogicalDatastoreType.CONFIGURATION, ipPortMapId);
418         if (ipPortMapData.isPresent()) {
419             IpPortMap ipPortMapInstance = ipPortMapData.get();
420             return ipPortMapInstance.getIpPortExternal();
421         }
422         return null;
423     }
424
425     private static InstanceIdentifier<IpPortMap> buildIpToPortMapIdentifier(Long routerId, String internalIpAddress, String internalPort , ProtocolTypes protocolType) {
426         InstanceIdentifier<IpPortMap> ipPortMapId = InstanceIdentifier.builder(IntextIpPortMap.class).child
427                 (IpPortMapping.class, new IpPortMappingKey(routerId)).child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
428                 .child(IpPortMap.class, new IpPortMapKey(internalIpAddress + ":" + internalPort)).build();
429         return ipPortMapId;
430     }
431
432     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId, int priority, String flowName,
433                                              BigInteger cookie, List<MatchInfo> listMatchInfo) {
434
435         FlowEntity flowEntity = new FlowEntity(dpnId);
436         flowEntity.setTableId(tableId);
437         flowEntity.setFlowId(flowId);
438         flowEntity.setPriority(priority);
439         flowEntity.setFlowName(flowName);
440         flowEntity.setCookie(cookie);
441         flowEntity.setMatchInfoList(listMatchInfo);
442         return flowEntity;
443     }
444
445     static boolean isVpnInterfaceConfigured(DataBroker broker, String interfaceName)
446     {
447         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
448         Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
449
450         if (configuredVpnInterface.isPresent()) {
451             return true;
452         }
453         return false;
454     }
455
456     static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
457         return InstanceIdentifier.builder(VpnInterfaces.class)
458                 .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build();
459     }
460
461     static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
462         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
463         Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
464
465         if (configuredVpnInterface.isPresent()) {
466             return configuredVpnInterface.get();
467         }
468         return null;
469     }
470
471     public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
472         /*
473          * NodeConnectorId is of form 'openflow:dpnid:portnum'
474          */
475         String[] split = portId.getValue().split(OF_URI_SEPARATOR);
476         return split[1];
477     }
478
479     public static BigInteger getDpIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
480         String lowerLayerIf = ifState.getLowerLayerIf().get(0);
481         NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
482         return new BigInteger(getDpnFromNodeConnectorId(nodeConnectorId));
483     }
484
485
486     /*
487     container vpnMaps {
488         list vpnMap {
489             key vpn-id;
490             leaf vpn-id {
491                 type    yang:uuid;
492                 description "vpn-id";
493             }
494             leaf name {
495                 type  string;
496                 description "vpn name";
497             }
498             leaf tenant-id {
499                 type    yang:uuid;
500                 description "The UUID of the tenant that will own the subnet.";
501             }
502
503             leaf router-id {
504               type    yang:uuid;
505               description "UUID of router ";
506             }
507             leaf-list network_ids {
508               type    yang:uuid;
509               description "UUID representing the network ";
510             }
511         }
512     }
513     Method returns router Id associated to a VPN
514      */
515
516     public static String getRouterIdfromVpnId(DataBroker broker,String vpnName){
517         InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
518                 .child(VpnMap.class, new VpnMapKey(new Uuid(vpnName))).build();
519         Optional<VpnMap> optionalVpnMap = read(broker, LogicalDatastoreType.CONFIGURATION,
520                 vpnMapIdentifier);
521         if (optionalVpnMap.isPresent()) {
522             return optionalVpnMap.get().getRouterId().getValue();
523         }
524         return null;
525     }
526
527
528     public static List<VpnToDpnList> getVpnToDpnList(DataBroker dataBroker, String vrfId )
529     {
530         List<VpnToDpnList> vpnDpnList = null;
531
532         InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier
533                 .builder(VpnInstanceOpData.class)
534                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vrfId))
535                 .build();
536
537         Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
538
539         if(vpnInstanceOpData.isPresent())
540         {
541             VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnInstanceOpData.get();
542             vpnDpnList = vpnInstanceOpDataEntry.getVpnToDpnList();
543         }
544
545         return vpnDpnList;
546     }
547
548     public static String getAssociatedVPN(DataBroker dataBroker, Uuid networkId, Logger log) {
549         Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
550         if(vpnUuid == null ){
551             log.error("No VPN instance associated with ext network {}", networkId);
552             return null;
553         }
554         return vpnUuid.getValue();
555     }
556
557     public static void addPrefixToBGP(IBgpManager bgpManager, String rd, String prefix, String nextHopIp, long label, Logger log) {
558         try {
559             bgpManager.addPrefix(rd, prefix, nextHopIp, (int)label);
560         } catch(Exception e) {
561             log.error("Add prefix failed", e);
562         }
563     }
564
565     static InstanceIdentifier<Ports> buildPortToIpMapIdentifier(String routerId, String portName) {
566         InstanceIdentifier<Ports> ipPortMapId = InstanceIdentifier.builder(FloatingIpInfo.class).child
567                 (RouterPorts.class, new RouterPortsKey(routerId)).child(Ports.class, new PortsKey(portName)).build();
568         return ipPortMapId;
569     }
570
571     static InstanceIdentifier<RouterPorts> buildRouterPortsIdentifier(String routerId) {
572         InstanceIdentifier<RouterPorts> routerInstanceIndentifier = InstanceIdentifier.builder(FloatingIpInfo.class).child
573                 (RouterPorts.class, new RouterPortsKey(routerId)).build();
574         return routerInstanceIndentifier;
575     }
576
577     /* container snatint-ip-port-map {
578         list intip-port-map {
579             key router-id;
580             leaf router-id { type uint32; }
581             list ip-port {
582                 key internal-ip;
583                 leaf internal-ip { type string; }
584                 list int-ip-proto-type {
585                     key protocol;
586                     leaf protocol { type protocol-types; }
587                     leaf-list ports { type uint16; }
588                 }
589             }
590         }
591     }
592     Method returns InternalIp port List
593     */
594
595     public static List<Integer> getInternalIpPortListInfo(DataBroker dataBroker,Long routerId, String internalIpAddress, ProtocolTypes protocolType){
596         Optional<IntIpProtoType> optionalIpProtoType = read(dataBroker, LogicalDatastoreType.CONFIGURATION, buildSnatIntIpPortIdentifier(routerId, internalIpAddress, protocolType));
597         if (optionalIpProtoType.isPresent()) {
598             return optionalIpProtoType.get().getPorts();
599         }
600         return null;
601     }
602
603     public static InstanceIdentifier<IntIpProtoType> buildSnatIntIpPortIdentifier(Long routerId, String internalIpAddress, ProtocolTypes protocolType) {
604         InstanceIdentifier<IntIpProtoType> intIpProtocolTypeId = InstanceIdentifier.builder(SnatintIpPortMap.class).child
605                 (IntipPortMap.class, new IntipPortMapKey(routerId)).child(IpPort.class, new IpPortKey(internalIpAddress)).child
606                 (IntIpProtoType.class, new IntIpProtoTypeKey(protocolType)).build();
607         return intIpProtocolTypeId;
608     }
609
610     public static ProtocolTypes getProtocolType(NAPTEntryEvent.Protocol protocol) {
611         ProtocolTypes protocolType = ProtocolTypes.TCP.toString().equals(protocol.toString()) ? ProtocolTypes.TCP : ProtocolTypes.UDP;
612         return protocolType;
613     }
614
615     public static NaptSwitches getNaptSwitch(DataBroker broker) {
616         Optional<NaptSwitches> switchesOptional = read(broker, LogicalDatastoreType.OPERATIONAL, getNaptSwitchesIdentifier());
617         if(switchesOptional.isPresent()) {
618             return switchesOptional.get();
619         }
620         return null;
621     }
622
623     public static InstanceIdentifier<NaptSwitches> getNaptSwitchesIdentifier() {
624         return InstanceIdentifier.create(NaptSwitches.class);
625     }
626
627     public static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchRouterIdentifier(String routerId) {
628         return InstanceIdentifier.create(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerId));
629     }
630
631     public static String toStringIpAddress(byte[] ipAddress, Logger log)
632     {
633       String ip = "";
634       if (ipAddress == null) {
635         return ip;
636       }
637
638       try {
639         ip = InetAddress.getByAddress(ipAddress).getHostAddress();
640       } catch(UnknownHostException e) {
641         log.error("NAT Service : Caught exception during toStringIpAddress()");
642       }
643
644       return ip;
645     }
646
647     public static String getGroupIdKey(String routerName){
648         String groupIdKey = new String("snatmiss." + routerName);
649         return groupIdKey;
650     }
651
652     public static long createGroupId(String groupIdKey,IdManagerService idManager) {
653         AllocateIdInput getIdInput = new AllocateIdInputBuilder()
654                 .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
655                 .build();
656         try {
657             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
658             RpcResult<AllocateIdOutput> rpcResult = result.get();
659             return rpcResult.getResult().getIdValue();
660         } catch (NullPointerException | InterruptedException | ExecutionException e) {
661             LOG.trace("", e);
662         }
663         return 0;
664     }
665
666     public static void removePrefixFromBGP(IBgpManager bgpManager, String rd, String prefix, Logger log) {
667         try {
668             bgpManager.deletePrefix(rd, prefix);
669         } catch(Exception e) {
670             log.error("Delete prefix failed", e);
671         }
672     }
673
674     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, BigInteger cookie, String flowId) {
675         FlowEntity flowEntity = new FlowEntity(dpnId);
676         flowEntity.setTableId(tableId);
677         flowEntity.setCookie(cookie);
678         flowEntity.setFlowId(flowId);
679         return flowEntity;
680     }
681
682     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId) {
683         FlowEntity flowEntity = new FlowEntity(dpnId);
684         flowEntity.setTableId(tableId);
685         flowEntity.setFlowId(flowId);
686         return flowEntity;
687     }
688
689     public static IpPortMapping getIportMapping(DataBroker broker, long routerId) {
690         Optional<IpPortMapping> getIportMappingData = read(broker, LogicalDatastoreType.CONFIGURATION, getIportMappingIdentifier(routerId));
691         if(getIportMappingData.isPresent()) {
692             return getIportMappingData.get();
693         }
694         return null;
695     }
696
697     public static InstanceIdentifier<IpPortMapping> getIportMappingIdentifier(long routerId) {
698         return InstanceIdentifier.builder(IntextIpPortMap.class).child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
699     }
700 }