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