Remove unused imports in class VpnUtil
[netvirt.git] / vpnservice / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / netvirt / vpnmanager / VpnUtil.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.vpnmanager;
10
11 import com.google.common.base.Optional;
12 import com.google.common.primitives.Ints;
13 import com.google.common.util.concurrent.CheckedFuture;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
16 import java.math.BigInteger;
17 import java.net.InetAddress;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.List;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.Future;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
25 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
26 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
29 import org.opendaylight.genius.mdsalutil.FlowEntity;
30 import org.opendaylight.genius.mdsalutil.InstructionInfo;
31 import org.opendaylight.genius.mdsalutil.InstructionType;
32 import org.opendaylight.genius.mdsalutil.MDSALUtil;
33 import org.opendaylight.genius.mdsalutil.MatchFieldType;
34 import org.opendaylight.genius.mdsalutil.MatchInfo;
35 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
36 import org.opendaylight.genius.mdsalutil.NwConstants;
37 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
38 import org.opendaylight.genius.utils.cache.DataStoreCache;
39 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
40 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
41 import org.opendaylight.genius.utils.clustering.ClusteringUtils;
42 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
43 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
44 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
45 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
46 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
47 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
48 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
49 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
50 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
51 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdPools;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPool;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPoolKey;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.IfIndexesInterfaceMap;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._if.indexes._interface.map.IfIndexInterface;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._if.indexes._interface.map.IfIndexInterfaceKey;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockManagerService;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TimeUnits;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInputBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanTagNameMap;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagName;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagNameKey;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.L3nexthop;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthops;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthopsKey;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PrefixToInterface;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RouterInterfaces;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.LearntVpnVipToPortData;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnToExtraroute;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIds;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIdsBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIdsKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterface;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterfaceBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterfaceKey;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceBuilder;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.Vpn;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.VpnBuilder;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.VpnKey;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteBuilder;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPortBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPortKey;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
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.NaptSwitches;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.IpVersionBase;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.IpVersionV4;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
142 import org.opendaylight.yangtools.yang.binding.DataObject;
143 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
144 import org.opendaylight.yangtools.yang.common.RpcResult;
145 import org.opendaylight.yangtools.yang.data.impl.schema.tree.SchemaValidationFailedException;
146 import org.slf4j.Logger;
147 import org.slf4j.LoggerFactory;
148 import com.google.common.util.concurrent.ListenableFuture;
149
150 public class VpnUtil {
151     private static final Logger LOG = LoggerFactory.getLogger(VpnUtil.class);
152     private static final int DEFAULT_PREFIX_LENGTH = 32;
153     private static final String PREFIX_SEPARATOR = "/";
154
155     static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
156         return InstanceIdentifier.builder(VpnInterfaces.class)
157                 .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build();
158     }
159
160     static InstanceIdentifier<VpnInstance> getVpnInstanceIdentifier(String vpnName) {
161         return InstanceIdentifier.builder(VpnInstances.class)
162                 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
163     }
164
165     static VpnInterface getVpnInterface(String intfName, String vpnName, Adjacencies aug, BigInteger dpnId, Boolean isSheduledForRemove) {
166         return new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(intfName)).setVpnInstanceName(vpnName).setDpnId(dpnId)
167                 .setScheduledForRemove(isSheduledForRemove).addAugmentation(Adjacencies.class, aug)
168                 .build();
169     }
170
171     static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
172         return InstanceIdentifier.builder(PrefixToInterface.class)
173                 .child(VpnIds.class, new VpnIdsKey(vpnId)).child(Prefixes.class,
174                         new PrefixesKey(ipPrefix)).build();
175     }
176
177     static InstanceIdentifier<VpnIds> getPrefixToInterfaceIdentifier(long vpnId) {
178         return InstanceIdentifier.builder(PrefixToInterface.class)
179                 .child(VpnIds.class, new VpnIdsKey(vpnId)).build();
180     }
181
182     static VpnIds getPrefixToInterface(long vpnId) {
183         return new VpnIdsBuilder().setKey(new VpnIdsKey(vpnId)).setVpnId(vpnId).build();
184     }
185
186     static Prefixes getPrefixToInterface(BigInteger dpId, String vpnInterfaceName, String ipPrefix) {
187         return new PrefixesBuilder().setDpnId(dpId).setVpnInterfaceName(
188                 vpnInterfaceName).setIpAddress(ipPrefix).build();
189     }
190
191     static InstanceIdentifier<Extraroute> getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) {
192         return InstanceIdentifier.builder(VpnToExtraroute.class)
193                 .child(Vpn.class, new VpnKey(vrfId)).child(Extraroute.class,
194                         new ExtrarouteKey(ipPrefix)).build();
195     }
196
197     static InstanceIdentifier<Vpn> getVpnToExtrarouteIdentifier(String vrfId) {
198         return InstanceIdentifier.builder(VpnToExtraroute.class)
199                 .child(Vpn.class, new VpnKey(vrfId)).build();
200     }
201
202     static Vpn getVpnToExtraRoute(String vrfId) {
203         return new VpnBuilder().setKey(new VpnKey(vrfId)).setVrfId(vrfId).build();
204     }
205
206     /**
207      * Get VRF table given a Route Distinguisher
208      *
209      * @param broker dataBroker service reference
210      * @param rd Route-Distinguisher
211      * @return VrfTables that holds the list of VrfEntries of the specified rd
212      */
213     public static VrfTables getVrfTable(DataBroker broker, String rd) {
214         InstanceIdentifier<VrfTables> id =
215                 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
216         Optional<VrfTables> vrfTable = read(broker, LogicalDatastoreType.CONFIGURATION, id);
217         return vrfTable.isPresent() ? vrfTable.get() : null;
218     }
219
220     /**
221      * Retrieves the VrfEntries that belong to a given VPN filtered out by
222      * Origin, searching by its Route-Distinguisher
223      *
224      * @param broker dataBroker service reference
225      * @param rd     Route-distinguisher of the VPN
226      * @param originsToConsider Only entries whose origin is included in this
227      *     list will be considered
228      * @return the list of VrfEntries
229      */
230     public static List<VrfEntry> getVrfEntriesByOrigin(DataBroker broker, String rd,
231                                                        List<RouteOrigin> originsToConsider) {
232         List<VrfEntry> result = new ArrayList<VrfEntry>();
233         List<VrfEntry> allVpnVrfEntries = getAllVrfEntries(broker, rd);
234         for (VrfEntry vrfEntry : allVpnVrfEntries) {
235             if (originsToConsider.contains(RouteOrigin.value(vrfEntry.getOrigin()))) {
236                 result.add(vrfEntry);
237             }
238         }
239         return result;
240     }
241
242     static List<Prefixes> getAllPrefixesToInterface(DataBroker broker, long vpnId) {
243         Optional<VpnIds> vpnIds = read(broker, LogicalDatastoreType.OPERATIONAL, getPrefixToInterfaceIdentifier(vpnId));
244         if (vpnIds.isPresent()) {
245             return vpnIds.get().getPrefixes();
246         }
247         return new ArrayList<Prefixes>();
248     }
249
250     static List<Extraroute> getAllExtraRoutes(DataBroker broker, String vrfId) {
251         Optional<Vpn> extraRoutes = read(broker, LogicalDatastoreType.OPERATIONAL, getVpnToExtrarouteIdentifier(vrfId));
252         if (extraRoutes.isPresent()) {
253             return extraRoutes.get().getExtraroute();
254         }
255         return new ArrayList<Extraroute>();
256     }
257
258     /**
259      * Retrieves all the VrfEntries that belong to a given VPN searching by its
260      * Route-Distinguisher
261      *
262      * @param broker dataBroker service reference
263      * @param rd     Route-distinguisher of the VPN
264      * @return the list of VrfEntries
265      */
266     public static List<VrfEntry> getAllVrfEntries(DataBroker broker, String rd) {
267         VrfTables vrfTables = VpnUtil.getVrfTable(broker, rd);
268         return (vrfTables != null) ? vrfTables.getVrfEntry() : new ArrayList<VrfEntry>();
269     }
270
271     //FIXME: Implement caches for DS reads
272     public static VpnInstance getVpnInstance(DataBroker broker, String vpnInstanceName) {
273         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class,
274                 new VpnInstanceKey(vpnInstanceName)).build();
275         Optional<VpnInstance> vpnInstance = read(broker, LogicalDatastoreType.CONFIGURATION, id);
276         return (vpnInstance.isPresent()) ? vpnInstance.get() : null;
277     }
278
279     static List<VpnInstance> getAllVpnInstances(DataBroker broker) {
280         InstanceIdentifier<VpnInstances> id = InstanceIdentifier.builder(VpnInstances.class).build();
281         Optional<VpnInstances> optVpnInstances = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
282         if (optVpnInstances.isPresent()) {
283             return optVpnInstances.get().getVpnInstance();
284         } else {
285             return Collections.emptyList();
286         }
287     }
288
289     static List<VpnInstanceOpDataEntry> getAllVpnInstanceOpData(DataBroker broker) {
290         InstanceIdentifier<VpnInstanceOpData> id = InstanceIdentifier.builder(VpnInstanceOpData.class).build();
291         Optional<VpnInstanceOpData> vpnInstanceOpDataOptional = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
292         if (vpnInstanceOpDataOptional.isPresent()) {
293             return vpnInstanceOpDataOptional.get().getVpnInstanceOpDataEntry();
294         } else {
295             return new ArrayList<VpnInstanceOpDataEntry>();
296         }
297     }
298
299     public static List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn
300             .instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> getDpnVpnInterfaces(DataBroker broker,
301                     VpnInstance vpnInstance, BigInteger dpnId) {
302         String rd = getRdFromVpnInstance(vpnInstance);
303         InstanceIdentifier<VpnToDpnList> dpnToVpnId = getVpnToDpnListIdentifier(rd, dpnId);
304         Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, dpnToVpnId);
305         return dpnInVpn.isPresent() ? dpnInVpn.get().getVpnInterfaces() : Collections.emptyList();
306     }
307
308     public static String getRdFromVpnInstance(VpnInstance vpnInstance) {
309         VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
310         LOG.trace("vpnConfig {}", vpnConfig);
311         String rd = vpnConfig.getRouteDistinguisher();
312         if (rd == null || rd.isEmpty()) {
313             rd = vpnInstance.getVpnInstanceName();
314             LOG.trace("rd is null or empty. Assigning VpnInstanceName to rd {}", rd);
315         }
316
317         return rd;
318     }
319
320     static VrfEntry getVrfEntry(DataBroker broker, String rd, String ipPrefix) {
321
322         VrfTables vrfTable = getVrfTable(broker, rd);
323         // TODO: why check VrfTables if we later go for the specific VrfEntry?
324         if (vrfTable != null) {
325             InstanceIdentifier<VrfEntry> vrfEntryId =
326                     InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).
327                             child(VrfEntry.class, new VrfEntryKey(ipPrefix)).build();
328             Optional<VrfEntry> vrfEntry = read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
329             if (vrfEntry.isPresent()) {
330                 return vrfEntry.get();
331             }
332         }
333         return null;
334     }
335
336     static List<Adjacency> getAdjacenciesForVpnInterfaceFromConfig(DataBroker broker, String intfName) {
337         final InstanceIdentifier<VpnInterface> identifier = getVpnInterfaceIdentifier(intfName);
338         InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
339         Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
340
341         if (adjacencies.isPresent()) {
342             List<Adjacency> nextHops = adjacencies.get().getAdjacency();
343             return nextHops;
344         }
345         return null;
346     }
347
348     static Extraroute getVpnToExtraroute(String ipPrefix, List<String> nextHopList) {
349         return new ExtrarouteBuilder().setPrefix(ipPrefix).setNexthopIpList(nextHopList).build();
350     }
351
352     public static List<Extraroute> getVpnExtraroutes(DataBroker broker, String vpnRd) {
353         InstanceIdentifier<Vpn> vpnExtraRoutesId =
354                 InstanceIdentifier.builder(VpnToExtraroute.class).child(Vpn.class, new VpnKey(vpnRd)).build();
355         Optional<Vpn> vpnOpc = read(broker, LogicalDatastoreType.OPERATIONAL, vpnExtraRoutesId);
356         return vpnOpc.isPresent() ? vpnOpc.get().getExtraroute() : new ArrayList<Extraroute>();
357     }
358
359     static Adjacencies getVpnInterfaceAugmentation(List<Adjacency> nextHopList) {
360         return new AdjacenciesBuilder().setAdjacency(nextHopList).build();
361     }
362
363     public static InstanceIdentifier<IdPool> getPoolId(String poolName) {
364         InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
365                 InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName));
366         InstanceIdentifier<IdPool> id = idBuilder.build();
367         return id;
368     }
369
370     static InstanceIdentifier<VpnInterfaces> getVpnInterfacesIdentifier() {
371         return InstanceIdentifier.builder(VpnInterfaces.class).build();
372     }
373
374     static InstanceIdentifier<Interface> getInterfaceIdentifier(String interfaceName) {
375         return InstanceIdentifier.builder(Interfaces.class)
376                 .child(Interface.class, new InterfaceKey(interfaceName)).build();
377     }
378
379     static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
380         return InstanceIdentifier.builder(VpnInstanceOpData.class)
381                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd))
382                 .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
383     }
384
385     public static BigInteger getCookieArpFlow(int interfaceTag) {
386         return VpnConstants.COOKIE_L3_BASE.add(new BigInteger("0110000", 16)).add(
387                 BigInteger.valueOf(interfaceTag));
388     }
389
390     public static BigInteger getCookieL3(int vpnId) {
391         return VpnConstants.COOKIE_L3_BASE.add(new BigInteger("0610000", 16)).add(BigInteger.valueOf(vpnId));
392     }
393
394     public static String getFlowRef(BigInteger dpnId, short tableId, int ethType, int lPortTag, int arpType) {
395         return new StringBuffer().append(VpnConstants.FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
396                 .append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(ethType).append(lPortTag)
397                 .append(NwConstants.FLOWID_SEPARATOR).append(arpType).toString();
398     }
399
400     public static int getUniqueId(IdManagerService idManager, String poolName, String idKey) {
401         AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
402
403         try {
404             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
405             RpcResult<AllocateIdOutput> rpcResult = result.get();
406             if (rpcResult.isSuccessful()) {
407                 return rpcResult.getResult().getIdValue().intValue();
408             } else {
409                 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
410             }
411         } catch (InterruptedException | ExecutionException e) {
412             LOG.warn("Exception when getting Unique Id", e);
413         }
414         return 0;
415     }
416
417     public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
418         ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
419         try {
420             Future<RpcResult<Void>> result = idManager.releaseId(idInput);
421             RpcResult<Void> rpcResult = result.get();
422             if (!rpcResult.isSuccessful()) {
423                 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
424             }
425         } catch (InterruptedException | ExecutionException e) {
426             LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
427         }
428     }
429
430     public static String getNextHopLabelKey(String rd, String prefix) {
431         return rd + VpnConstants.SEPARATOR + prefix;
432     }
433
434     /**
435      * Retrieves the VpnInstance name (typically the VPN Uuid) out from the
436      * route-distinguisher
437      *
438      * @param broker dataBroker service reference
439      * @param rd Route-Distinguisher
440      * @return the VpnInstance name
441      */
442     public static String getVpnNameFromRd(DataBroker broker, String rd) {
443         VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(broker, rd);
444         return (vpnInstanceOpData != null) ? vpnInstanceOpData.getVpnInstanceName() : null;
445     }
446
447     /**
448      * Retrieves the dataplane identifier of a specific VPN, searching by its
449      * VpnInstance name.
450      *
451      * @param broker dataBroker service reference
452      * @param vpnName Name of the VPN
453      * @return the dataplane identifier of the VPN, the VrfTag.
454      */
455     public static long getVpnId(DataBroker broker, String vpnName) {
456
457         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
458                 = getVpnInstanceToVpnIdIdentifier(vpnName);
459         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
460                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
461
462         long vpnId = VpnConstants.INVALID_ID;
463         if (vpnInstance.isPresent()) {
464             vpnId = vpnInstance.get().getVpnId();
465         }
466         return vpnId;
467     }
468
469     /**
470      * Retrieves the VPN Route Distinguisher searching by its Vpn instance name
471      *
472      * @param broker dataBroker service reference
473      * @param vpnName Name of the VPN
474      * @return the route-distinguisher of the VPN
475      */
476     public static String getVpnRd(DataBroker broker, String vpnName) {
477         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
478                 = getVpnInstanceToVpnIdIdentifier(vpnName);
479         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
480                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
481
482         String rd = null;
483         if (vpnInstance.isPresent()) {
484             rd = vpnInstance.get().getVrfId();
485         }
486         return rd;
487     }
488
489     /**
490      * Get VPN Route Distinguisher from VPN Instance Configuration
491      *
492      * @param broker dataBroker service reference
493      * @param vpnName Name of the VPN
494      * @return the route-distinguisher of the VPN
495      */
496     public static String getVpnRdFromVpnInstanceConfig(DataBroker broker, String vpnName) {
497         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
498                 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
499         Optional<VpnInstance> vpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
500         String rd = null;
501         if (vpnInstance.isPresent()) {
502             VpnInstance instance = vpnInstance.get();
503             VpnAfConfig config = instance.getIpv4Family();
504             rd = config.getRouteDistinguisher();
505         }
506         return rd;
507     }
508
509     /**
510      * Remove from MDSAL all those VrfEntries in a VPN that have an specific RouteOrigin
511      *
512      * @param broker dataBroker service reference
513      * @param rd     Route Distinguisher
514      * @param origin Origin of the Routes to be removed (see {@link RouteOrigin})
515      */
516     public static void removeVrfEntriesByOrigin(DataBroker broker, String rd, RouteOrigin origin) {
517         InstanceIdentifier<VrfTables> vpnVrfTableIid =
518                 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
519         Optional<VrfTables> vrfTablesOpc = read(broker, LogicalDatastoreType.CONFIGURATION, vpnVrfTableIid);
520         if (vrfTablesOpc.isPresent()) {
521             VrfTables vrfTables = vrfTablesOpc.get();
522             WriteTransaction tx = broker.newWriteOnlyTransaction();
523             for (VrfEntry vrfEntry : vrfTables.getVrfEntry()) {
524                 if (origin == RouteOrigin.value(vrfEntry.getOrigin())) {
525                     tx.delete(LogicalDatastoreType.CONFIGURATION, vpnVrfTableIid.child(VrfEntry.class, vrfEntry.getKey()));
526                 }
527             }
528             tx.submit();
529         }
530     }
531
532     public static List<VrfEntry> findVrfEntriesByNexthop(DataBroker broker, String rd, String nexthop) {
533         InstanceIdentifier<VrfTables> vpnVrfTableIid =
534                 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
535         Optional<VrfTables> vrfTablesOpc = read(broker, LogicalDatastoreType.CONFIGURATION, vpnVrfTableIid);
536         List<VrfEntry> matches = new ArrayList<VrfEntry>();
537
538         if (vrfTablesOpc.isPresent()) {
539             VrfTables vrfTables = vrfTablesOpc.get();
540             for (VrfEntry vrfEntry : vrfTables.getVrfEntry()) {
541                 if (vrfEntry.getNextHopAddressList() != null && vrfEntry.getNextHopAddressList().contains(nexthop)) {
542                     matches.add(vrfEntry);
543                 }
544             }
545         }
546         return matches;
547     }
548
549     public static void removeVrfEntries(DataBroker broker, String rd, List<VrfEntry> vrfEntries) {
550         InstanceIdentifier<VrfTables> vpnVrfTableIid =
551             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
552         WriteTransaction tx = broker.newWriteOnlyTransaction();
553         for (VrfEntry vrfEntry : vrfEntries) {
554             tx.delete(LogicalDatastoreType.CONFIGURATION, vpnVrfTableIid.child(VrfEntry.class, vrfEntry.getKey()));
555         }
556         tx.submit();
557     }
558
559     public static void withdrawRoutes(IBgpManager bgpManager, String rd, List<VrfEntry> vrfEntries) {
560         vrfEntries.forEach(vrfEntry -> {
561             try {
562                 bgpManager.withdrawPrefix(rd, vrfEntry.getDestPrefix());
563             } catch (Exception e) {
564                 LOG.error("Could not withdraw route to {} with nextHop {} in VpnRd {}",
565                           vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList(), rd);
566             }
567         });
568     }
569
570     static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
571                 getVpnInstanceToVpnId(String vpnName, long vpnId, String rd) {
572
573         return new VpnInstanceBuilder().setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).build();
574
575     }
576
577     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
578                 getVpnInstanceToVpnIdIdentifier(String vpnName) {
579         return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
580                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
581                         new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
582     }
583
584     static RouterInterface getConfiguredRouterInterface(DataBroker broker, String interfaceName) {
585         Optional<RouterInterface> optRouterInterface = read(broker, LogicalDatastoreType.CONFIGURATION, VpnUtil.getRouterInterfaceId(interfaceName));
586         if(optRouterInterface.isPresent()) {
587             return optRouterInterface.get();
588         }
589         return null;
590     }
591
592     static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds
593                 getVpnIdToVpnInstance(long vpnId, String vpnName, String rd, boolean isExternalVpn) {
594         return new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsBuilder()
595                 .setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).setExternalVpn(isExternalVpn).build();
596
597     }
598
599     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds>
600         getVpnIdToVpnInstanceIdentifier(long vpnId) {
601         return InstanceIdentifier.builder(VpnIdToVpnInstance.class)
602                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds.class,
603                         new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsKey(Long.valueOf(vpnId))).build();
604     }
605
606     /**
607      * Retrieves the Vpn Name searching by its VPN Tag.
608      *
609      * @param broker dataBroker service reference
610      * @param vpnId Dataplane identifier of the VPN
611      * @return the Vpn instance name
612      */
613     public static String getVpnName(DataBroker broker, long vpnId) {
614
615         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds> id
616                 = getVpnIdToVpnInstanceIdentifier(vpnId);
617         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds> vpnInstance
618                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
619
620         String vpnName = null;
621         if (vpnInstance.isPresent()) {
622             vpnName = vpnInstance.get().getVpnInstanceName();
623         }
624         return vpnName;
625     }
626
627     public static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
628         return InstanceIdentifier.builder(VpnInstanceOpData.class)
629                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
630     }
631
632     static InstanceIdentifier<RouterInterface> getRouterInterfaceId(String interfaceName) {
633         return InstanceIdentifier.builder(RouterInterfaces.class)
634                 .child(RouterInterface.class, new RouterInterfaceKey(interfaceName)).build();
635     }
636
637     static RouterInterface getRouterInterface(String interfaceName, String routerName) {
638         return new RouterInterfaceBuilder().setKey(new RouterInterfaceKey(interfaceName))
639                 .setInterfaceName(interfaceName).setRouterName(routerName).build();
640     }
641
642     public static VpnInstanceOpDataEntry getVpnInstanceOpData(DataBroker broker, String rd) {
643         InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
644         return read(broker, LogicalDatastoreType.OPERATIONAL, id).orNull();
645     }
646
647     static VpnInstanceOpDataEntry getVpnInstanceOpDataFromCache(DataBroker broker, String rd) {
648         InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
649         return (VpnInstanceOpDataEntry) DataStoreCache.get(VpnConstants.VPN_OP_INSTANCE_CACHE_NAME, id, rd, broker, false);
650     }
651
652     static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
653         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
654         Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
655
656         if (configuredVpnInterface.isPresent()) {
657             return configuredVpnInterface.get();
658         }
659         return null;
660     }
661
662     static String getNeutronRouterFromInterface(DataBroker broker, String interfaceName) {
663         InstanceIdentifier.InstanceIdentifierBuilder<RouterInterfacesMap> idBuilder =
664                             InstanceIdentifier.builder(RouterInterfacesMap.class);
665         InstanceIdentifier<RouterInterfacesMap> id = idBuilder.build();
666         Optional<RouterInterfacesMap> RouterInterfacesMap = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
667         if (RouterInterfacesMap.isPresent()) {
668               List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces> rtrInterfaces = RouterInterfacesMap.get().getRouterInterfaces();
669               for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces rtrInterface : rtrInterfaces) {
670                   List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces> rtrIfc = rtrInterface.getInterfaces();
671                   for(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces ifc : rtrIfc) {
672                       if (ifc.getInterfaceId().equals(interfaceName)) {
673                           return rtrInterface.getRouterId().getValue();
674                       }
675                   }
676               }
677         }
678         return null;
679     }
680
681     static VpnInterface getOperationalVpnInterface(DataBroker broker, String interfaceName) {
682         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
683         Optional<VpnInterface> operationalVpnInterface = read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
684
685         if (operationalVpnInterface.isPresent()) {
686             return operationalVpnInterface.get();
687         }
688         return null;
689     }
690
691     static boolean isVpnInterfaceConfigured(DataBroker broker, String interfaceName) {
692         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
693         Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
694
695         if (configuredVpnInterface.isPresent()) {
696             return true;
697         }
698         return false;
699     }
700
701     static boolean isInterfaceAssociatedWithVpn(DataBroker broker, String vpnName, String interfaceName) {
702         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
703         Optional<VpnInterface> optConfiguredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
704
705         if (optConfiguredVpnInterface.isPresent()) {
706             String configuredVpnName = optConfiguredVpnInterface.get().getVpnInstanceName();
707             if ((configuredVpnName != null) && (configuredVpnName.equalsIgnoreCase(vpnName))) {
708                 return true;
709             }
710         }
711         return false;
712     }
713
714     static String getIpPrefix(String prefix) {
715         String prefixValues[] = prefix.split("/");
716         if (prefixValues.length == 1) {
717             prefix = prefix + PREFIX_SEPARATOR + DEFAULT_PREFIX_LENGTH;
718         }
719         return prefix;
720     }
721
722     static final FutureCallback<Void> DEFAULT_CALLBACK =
723             new FutureCallback<Void>() {
724                 @Override
725                 public void onSuccess(Void result) {
726                     LOG.debug("Success in Datastore operation");
727                 }
728
729                 @Override
730                 public void onFailure(Throwable error) {
731                     LOG.error("Error in Datastore operation", error);
732                 }
733
734                 ;
735             };
736
737     public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
738                                                           InstanceIdentifier<T> path) {
739
740         ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
741
742         Optional<T> result = Optional.absent();
743         try {
744             result = tx.read(datastoreType, path).get();
745         } catch (Exception e) {
746             throw new RuntimeException(e);
747         } finally {
748             tx.close();
749         }
750
751         return result;
752     }
753
754     public static <T extends DataObject> void asyncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
755                                                           InstanceIdentifier<T> path, T data) {
756         asyncUpdate(broker, datastoreType, path, data, DEFAULT_CALLBACK);
757     }
758
759     public static <T extends DataObject> void asyncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
760                                                           InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
761         WriteTransaction tx = broker.newWriteOnlyTransaction();
762         tx.merge(datastoreType, path, data, true);
763         Futures.addCallback(tx.submit(), callback);
764     }
765
766     public static <T extends DataObject> void asyncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
767                                                          InstanceIdentifier<T> path, T data) {
768         asyncWrite(broker, datastoreType, path, data, DEFAULT_CALLBACK);
769     }
770
771     public static <T extends DataObject> void asyncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
772                                                          InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
773         WriteTransaction tx = broker.newWriteOnlyTransaction();
774         tx.put(datastoreType, path, data, true);
775         Futures.addCallback(tx.submit(), callback);
776     }
777
778     public static <T extends DataObject> void tryDelete(DataBroker broker, LogicalDatastoreType datastoreType,
779                                                      InstanceIdentifier<T> path) {
780         try {
781             delete(broker, datastoreType, path, DEFAULT_CALLBACK);
782         } catch ( SchemaValidationFailedException sve ) {
783             LOG.info("Could not delete {}. SchemaValidationFailedException: {}", path, sve.getMessage());
784         } catch ( Exception e) {
785             LOG.info("Could not delete {}. Unhandled error: {}", path, e.getMessage());
786         }
787     }
788
789     public static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
790                                                      InstanceIdentifier<T> path) {
791         delete(broker, datastoreType, path, DEFAULT_CALLBACK);
792     }
793
794
795     public static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
796                                                      InstanceIdentifier<T> path, FutureCallback<Void> callback) {
797         WriteTransaction tx = broker.newWriteOnlyTransaction();
798         tx.delete(datastoreType, path);
799         Futures.addCallback(tx.submit(), callback);
800     }
801
802     public static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
803                                                         InstanceIdentifier<T> path, T data) {
804         WriteTransaction tx = broker.newWriteOnlyTransaction();
805         tx.put(datastoreType, path, data, true);
806         CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
807         try {
808             futures.get();
809         } catch (InterruptedException | ExecutionException e) {
810             LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
811             throw new RuntimeException(e.getMessage());
812         }
813     }
814
815     public static <T extends DataObject> void syncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
816                                                          InstanceIdentifier<T> path, T data) {
817         WriteTransaction tx = broker.newWriteOnlyTransaction();
818         tx.merge(datastoreType, path, data, true);
819         CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
820         try {
821             futures.get();
822         } catch (InterruptedException | ExecutionException e) {
823             LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
824             throw new RuntimeException(e.getMessage());
825         }
826     }
827
828     public static long getRemoteBCGroup(long elanTag) {
829         return VpnConstants.ELAN_GID_MIN + ((elanTag % VpnConstants.ELAN_GID_MIN) * 2);
830     }
831
832     // interface-index-tag operational container
833     public static IfIndexInterface getInterfaceInfoByInterfaceTag(DataBroker broker, long interfaceTag) {
834         InstanceIdentifier<IfIndexInterface> interfaceId = getInterfaceInfoEntriesOperationalDataPath(interfaceTag);
835         Optional<IfIndexInterface> existingInterfaceInfo = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
836         if (existingInterfaceInfo.isPresent()) {
837             return existingInterfaceInfo.get();
838         }
839         return null;
840     }
841
842     private static InstanceIdentifier<IfIndexInterface> getInterfaceInfoEntriesOperationalDataPath(long interfaceTag) {
843         return InstanceIdentifier.builder(IfIndexesInterfaceMap.class).child(IfIndexInterface.class,
844                 new IfIndexInterfaceKey((int) interfaceTag)).build();
845     }
846
847     public static ElanTagName getElanInfoByElanTag(DataBroker broker, long elanTag) {
848         InstanceIdentifier<ElanTagName> elanId = getElanInfoEntriesOperationalDataPath(elanTag);
849         Optional<ElanTagName> existingElanInfo = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, elanId);
850         if (existingElanInfo.isPresent()) {
851             return existingElanInfo.get();
852         }
853         return null;
854     }
855
856     private static InstanceIdentifier<ElanTagName> getElanInfoEntriesOperationalDataPath(long elanTag) {
857         return InstanceIdentifier.builder(ElanTagNameMap.class).child(ElanTagName.class,
858                 new ElanTagNameKey(elanTag)).build();
859     }
860
861     /**
862      * Returns the Path identifier to reach a specific interface in a specific DPN in a given VpnInstance
863      *
864      * @param vpnRd     Route-Distinguisher of the VpnInstance
865      * @param dpnId     Id of the DPN where the interface is
866      * @param ifaceName Interface name
867      * @return the Instance Identifier
868      */
869     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
870             .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces>
871     getVpnToDpnInterfacePath(String vpnRd, BigInteger dpnId, String ifaceName) {
872
873         return
874                 InstanceIdentifier.builder(VpnInstanceOpData.class)
875                         .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vpnRd))
876                         .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId))
877                         .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
878                                 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
879                                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
880                                         .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey(ifaceName))
881                         .build();
882     }
883
884     public static void removePrefixToInterfaceForVpnId(DataBroker broker, long vpnId, WriteTransaction writeTxn) {
885         try {
886             // Clean up PrefixToInterface Operational DS
887             if (writeTxn != null) {
888                 writeTxn.delete(LogicalDatastoreType.OPERATIONAL,
889                         InstanceIdentifier.builder(PrefixToInterface.class).child(
890                                 VpnIds.class, new VpnIdsKey(vpnId)).build());
891             } else {
892                 delete(broker, LogicalDatastoreType.OPERATIONAL,
893                         InstanceIdentifier.builder(PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId)).build(),
894                         DEFAULT_CALLBACK);
895             }
896         } catch (Exception e) {
897             LOG.error("Exception during cleanup of PrefixToInterface for VPN ID {}", vpnId, e);
898         }
899     }
900
901     public static void removeVpnExtraRouteForVpn(DataBroker broker, String vpnName, WriteTransaction writeTxn) {
902         try {
903             // Clean up VPNExtraRoutes Operational DS
904             if (writeTxn != null) {
905                 writeTxn.delete(LogicalDatastoreType.OPERATIONAL,
906                         InstanceIdentifier.builder(VpnToExtraroute.class).child(Vpn.class, new VpnKey(vpnName)).build());
907             } else {
908                 delete(broker, LogicalDatastoreType.OPERATIONAL,
909                         InstanceIdentifier.builder(VpnToExtraroute.class).child(Vpn.class, new VpnKey(vpnName)).build(),
910                         DEFAULT_CALLBACK);
911             }
912         } catch (Exception e) {
913             LOG.error("Exception during cleanup of VPNToExtraRoute for VPN {}", vpnName, e);
914         }
915     }
916
917     public static void removeVpnOpInstance(DataBroker broker, String vpnName, WriteTransaction writeTxn) {
918         try {
919             // Clean up VPNInstanceOpDataEntry
920             if (writeTxn != null) {
921                 writeTxn.delete(LogicalDatastoreType.OPERATIONAL, getVpnInstanceOpDataIdentifier(vpnName));
922             } else {
923                 delete(broker, LogicalDatastoreType.OPERATIONAL, getVpnInstanceOpDataIdentifier(vpnName),
924                         DEFAULT_CALLBACK);
925             }
926         } catch (Exception e) {
927             LOG.error("Exception during cleanup of VPNInstanceOpDataEntry for VPN {}", vpnName, e);
928         }
929     }
930
931     public static void removeVpnInstanceToVpnId(DataBroker broker, String vpnName, WriteTransaction writeTxn) {
932         try {
933             if (writeTxn != null) {
934                 writeTxn.delete(LogicalDatastoreType.CONFIGURATION, getVpnInstanceToVpnIdIdentifier(vpnName));
935             } else {
936                 delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnInstanceToVpnIdIdentifier(vpnName),
937                         DEFAULT_CALLBACK);
938             }
939         } catch (Exception e) {
940             LOG.error("Exception during clean up of VpnInstanceToVpnId for VPN {}", vpnName, e);
941         }
942     }
943
944     public static void removeVpnIdToVpnInstance(DataBroker broker, long vpnId, WriteTransaction writeTxn) {
945         try {
946             if (writeTxn != null) {
947                 writeTxn.delete(LogicalDatastoreType.CONFIGURATION, getVpnIdToVpnInstanceIdentifier(vpnId));
948             } else {
949                 delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnIdToVpnInstanceIdentifier(vpnId),
950                         DEFAULT_CALLBACK);
951             }
952         } catch (Exception e) {
953             LOG.error("Exception during clean up of VpnIdToVpnInstance for VPNID {}", vpnId, e);
954         }
955     }
956
957     public static void removeVrfTableForVpn(DataBroker broker, String vpnName, WriteTransaction writeTxn) {
958         // Clean up FIB Entries Config DS
959         try {
960             if (writeTxn != null) {
961                 writeTxn.delete(LogicalDatastoreType.CONFIGURATION,
962                         InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(vpnName)).build());
963             } else {
964                 delete(broker, LogicalDatastoreType.CONFIGURATION,
965                         InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(vpnName)).build(),
966                         DEFAULT_CALLBACK);
967             }
968         } catch (Exception e) {
969             LOG.error("Exception during clean up of VrfTable from FIB for VPN {}", vpnName, e);
970         }
971     }
972
973     public static void removeL3nexthopForVpnId(DataBroker broker, long vpnId, WriteTransaction writeTxn) {
974         try {
975             // Clean up L3NextHop Operational DS
976             if (writeTxn != null) {
977                 writeTxn.delete(LogicalDatastoreType.OPERATIONAL,
978                         InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).build());
979             } else {
980                 delete(broker, LogicalDatastoreType.OPERATIONAL,
981                         InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).build(),
982                         DEFAULT_CALLBACK);
983             }
984         } catch (Exception e) {
985             LOG.error("Exception during cleanup of L3NextHop for VPN ID {}", vpnId, e);
986         }
987     }
988
989     public static void scheduleVpnInterfaceForRemoval(DataBroker broker,String interfaceName, BigInteger dpnId,
990                                                       String vpnInstanceName, Boolean isScheduledToRemove,
991                                                       WriteTransaction writeOperTxn){
992         InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
993         VpnInterface interfaceToUpdate = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(interfaceName)).setName(interfaceName)
994                 .setDpnId(dpnId).setVpnInstanceName(vpnInstanceName).setScheduledForRemove(isScheduledToRemove).build();
995         if (writeOperTxn != null) {
996             writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate, true);
997         } else {
998             VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate);
999         }
1000     }
1001
1002     protected static void createLearntVpnVipToPort(DataBroker broker, String vpnName, String fixedIp, String
1003             portName, String macAddress) {
1004         synchronized ((vpnName + fixedIp).intern()) {
1005             InstanceIdentifier<LearntVpnVipToPort> id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp);
1006             LearntVpnVipToPortBuilder builder = new LearntVpnVipToPortBuilder().setKey(
1007                     new LearntVpnVipToPortKey(fixedIp, vpnName)).setVpnName(vpnName).setPortFixedip(fixedIp).setPortName
1008                     (portName).setMacAddress(macAddress.toLowerCase());
1009             MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, builder.build());
1010             LOG.debug("ARP learned for fixedIp: {}, vpn {}, interface {}, mac {}, isSubnetIp {} added to " +
1011                     "VpnPortipToPort DS", fixedIp, vpnName, portName, macAddress);
1012         }
1013     }
1014
1015     private static InstanceIdentifier<LearntVpnVipToPort> buildLearntVpnVipToPortIdentifier(String vpnName, String fixedIp) {
1016         InstanceIdentifier<LearntVpnVipToPort> id = InstanceIdentifier.builder(LearntVpnVipToPortData.class).child
1017                 (LearntVpnVipToPort.class, new LearntVpnVipToPortKey(fixedIp, vpnName)).build();
1018         return id;
1019     }
1020
1021     protected static void removeLearntVpnVipToPort(DataBroker broker, String vpnName, String fixedIp) {
1022         synchronized ((vpnName + fixedIp).intern()) {
1023             InstanceIdentifier<LearntVpnVipToPort> id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp);
1024             MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
1025             LOG.debug("Delete learned ARP for fixedIp: {}, vpn {} removed from VpnPortipToPort DS", fixedIp, vpnName);
1026         }
1027     }
1028
1029     static InstanceIdentifier<VpnPortipToPort> buildVpnPortipToPortIdentifier(String vpnName, String fixedIp) {
1030         InstanceIdentifier<VpnPortipToPort> id = InstanceIdentifier.builder(NeutronVpnPortipPortData.class).child
1031                 (VpnPortipToPort.class, new VpnPortipToPortKey(fixedIp, vpnName)).build();
1032         return id;
1033     }
1034
1035     static VpnPortipToPort getNeutronPortFromVpnPortFixedIp(DataBroker broker, String vpnName, String fixedIp) {
1036         InstanceIdentifier id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
1037         Optional<VpnPortipToPort> vpnPortipToPortData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
1038         if (vpnPortipToPortData.isPresent()) {
1039             return (vpnPortipToPortData.get());
1040         }
1041         return null;
1042     }
1043
1044     static LearntVpnVipToPort getLearntVpnVipToPort(DataBroker broker, String vpnName, String fixedIp) {
1045         InstanceIdentifier id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp);
1046         Optional<LearntVpnVipToPort> learntVpnVipToPort = read(broker, LogicalDatastoreType.OPERATIONAL, id);
1047         if (learntVpnVipToPort.isPresent()) {
1048             return (learntVpnVipToPort.get());
1049         }
1050         return null;
1051     }
1052
1053     public static List<BigInteger> getDpnsOnVpn(DataBroker dataBroker, String vpnInstanceName) {
1054         List<BigInteger> result = new ArrayList<BigInteger>();
1055         String rd = getVpnRd(dataBroker, vpnInstanceName);
1056         if ( rd == null ) {
1057             LOG.debug("Could not find Route-Distinguisher for VpnName={}", vpnInstanceName);
1058             return result;
1059         }
1060
1061         VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(dataBroker, rd);
1062         if ( vpnInstanceOpData == null ) {
1063             LOG.debug("Could not find OpState for VpnName={}", vpnInstanceName);
1064             return result;
1065         }
1066
1067         List<VpnToDpnList> vpnToDpnList = vpnInstanceOpData.getVpnToDpnList();
1068         if ( vpnToDpnList == null ) {
1069             LOG.debug("Could not find DPN footprint for VpnName={}", vpnInstanceName);
1070             return result;
1071         }
1072         for ( VpnToDpnList vpnToDpn : vpnToDpnList) {
1073             result.add(vpnToDpn.getDpnId());
1074         }
1075         return result;
1076     }
1077
1078     static String getAssociatedExternalNetwork(DataBroker dataBroker, String routerId) {
1079         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerId);
1080         Optional<Routers> routerData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
1081         if (routerData.isPresent()) {
1082             Uuid networkId = routerData.get().getNetworkId();
1083             if(networkId != null) {
1084                 return networkId.getValue();
1085             }
1086         }
1087         return null;
1088     }
1089
1090     static InstanceIdentifier<Routers> buildRouterIdentifier(String routerId) {
1091         InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
1092                 (Routers.class, new RoutersKey(routerId)).build();
1093         return routerInstanceIndentifier;
1094     }
1095
1096     static Networks getExternalNetwork(DataBroker dataBroker, Uuid networkId) {
1097         InstanceIdentifier<Networks> netsIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
1098                 .child(Networks.class, new NetworksKey(networkId)).build();
1099         Optional<Networks> optionalNets = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, netsIdentifier);
1100         return optionalNets.isPresent() ? optionalNets.get() : null;
1101     }
1102
1103     static Uuid getExternalNetworkVpnId(DataBroker dataBroker, Uuid networkId) {
1104         Networks extNetwork = getExternalNetwork(dataBroker, networkId);
1105         return extNetwork != null ? extNetwork.getVpnid() : null;
1106     }
1107
1108     static List<Uuid> getExternalNetworkRouterIds(DataBroker dataBroker, Uuid networkId) {
1109         Networks extNetwork = getExternalNetwork(dataBroker, networkId);
1110         return extNetwork != null ? extNetwork.getRouterIds() : null;
1111     }
1112
1113     static Routers getExternalRouter(DataBroker dataBroker, String routerId) {
1114         InstanceIdentifier<Routers> id = InstanceIdentifier.builder(ExtRouters.class)
1115                 .child(Routers.class, new RoutersKey(routerId)).build();
1116         Optional<Routers> routerData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
1117         return routerData.isPresent() ? routerData.get() : null;
1118     }
1119
1120     static List<String> getAllSubnetGatewayMacAddressesforVpn(DataBroker broker, String vpnName) {
1121         List<String> macAddresses = new ArrayList<>();
1122         Optional<Subnetmaps> subnetMapsData = read(broker, LogicalDatastoreType.CONFIGURATION, buildSubnetMapsWildCardPath());
1123         if (subnetMapsData.isPresent()) {
1124             List<Subnetmap> subnetMapList = subnetMapsData.get().getSubnetmap();
1125             if (subnetMapList != null && !subnetMapList.isEmpty()) {
1126                 for (Subnetmap subnet: subnetMapList) {
1127                     if (subnet.getVpnId() !=null && subnet.getVpnId().equals(Uuid.getDefaultInstance(vpnName))) {
1128                         String routerIntfMacAddress = subnet.getRouterIntfMacAddress();
1129                         if (routerIntfMacAddress != null && !routerIntfMacAddress.isEmpty()) {
1130                             macAddresses.add(subnet.getRouterIntfMacAddress());
1131                         }
1132                     }
1133                 }
1134             }
1135         }
1136         return macAddresses;
1137     }
1138
1139     static InstanceIdentifier<Subnetmaps> buildSubnetMapsWildCardPath() {
1140         return InstanceIdentifier.create(Subnetmaps.class);
1141     }
1142
1143     static void setupSubnetMacIntoVpnInstance(DataBroker dataBroker, IMdsalApiManager mdsalManager,
1144             String vpnName, String srcMacAddress, BigInteger dpnId, WriteTransaction writeTx, int addOrRemove) {
1145         long vpnId = getVpnId(dataBroker, vpnName);
1146         if (dpnId.equals(BigInteger.ZERO)) {
1147             /* Apply the MAC on all DPNs in a VPN */
1148             List<BigInteger> dpIds = getDpnsOnVpn(dataBroker, vpnName);
1149             if (dpIds == null || dpIds.isEmpty()) {
1150                 return;
1151             }
1152             for (BigInteger dpId : dpIds) {
1153                 addGwMacIntoTx(mdsalManager, srcMacAddress, writeTx, addOrRemove, vpnId, dpId);
1154             }
1155         } else {
1156             addGwMacIntoTx(mdsalManager, srcMacAddress, writeTx, addOrRemove, vpnId, dpnId);
1157         }
1158     }
1159
1160     static void addGwMacIntoTx(IMdsalApiManager mdsalManager, String srcMacAddress, WriteTransaction writeTx,
1161             int addOrRemove, long vpnId, BigInteger dpId) {
1162         FlowEntity flowEntity = buildL3vpnGatewayFlow(dpId, srcMacAddress, vpnId);
1163         if (addOrRemove == NwConstants.ADD_FLOW) {
1164             mdsalManager.addFlowToTx(flowEntity, writeTx);
1165         } else {
1166             mdsalManager.removeFlowToTx(flowEntity, writeTx);
1167         }
1168     }
1169
1170     public static FlowEntity buildL3vpnGatewayFlow(BigInteger dpId, String gwMacAddress, long vpnId) {
1171         List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
1172         mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
1173                 MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
1174         mkMatches.add(new MatchInfo(MatchFieldType.eth_dst, new String[] { gwMacAddress }));
1175         List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
1176         mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.L3_FIB_TABLE }));
1177         String flowId = getL3VpnGatewayFlowRef(NwConstants.L3_GW_MAC_TABLE, dpId, vpnId, gwMacAddress);
1178         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_GW_MAC_TABLE,
1179                 flowId, 20, flowId, 0, 0, NwConstants.COOKIE_L3_GW_MAC_TABLE, mkMatches, mkInstructions);
1180         return flowEntity;
1181     }
1182
1183     private static String getL3VpnGatewayFlowRef(short l3GwMacTable, BigInteger dpId, long vpnId, String gwMacAddress) {
1184         return gwMacAddress+NwConstants.FLOWID_SEPARATOR+vpnId+NwConstants.FLOWID_SEPARATOR+dpId+NwConstants.FLOWID_SEPARATOR+l3GwMacTable;
1185     }
1186
1187     public static void lockSubnet(LockManagerService lockManager, String subnetId) {
1188         TryLockInput input = new TryLockInputBuilder().setLockName(subnetId).setTime(3000L).setTimeUnit(TimeUnits.Milliseconds).build();
1189         Future<RpcResult<Void>> result = lockManager.tryLock(input);
1190         String errMsg = "Unable to getLock for subnet " + subnetId;
1191         try {
1192             if ((result != null) && (result.get().isSuccessful())) {
1193                     LOG.debug("Acquired lock for {}", subnetId);
1194             } else {
1195                 throw new RuntimeException(errMsg);
1196             }
1197         } catch (InterruptedException | ExecutionException e) {
1198             LOG.error(errMsg);
1199             throw new RuntimeException(errMsg, e.getCause());
1200         }
1201     }
1202
1203     public static void unlockSubnet(LockManagerService lockManager, String subnetId) {
1204         UnlockInput input = new UnlockInputBuilder().setLockName(subnetId).build();
1205         Future<RpcResult<Void>> result = lockManager.unlock(input);
1206         try {
1207             if ((result != null) && (result.get().isSuccessful())) {
1208                 LOG.debug("Unlocked {}", subnetId);
1209             } else {
1210                 LOG.debug("Unable to unlock subnet {}", subnetId);
1211             }
1212         } catch (InterruptedException | ExecutionException e) {
1213             LOG.error("Unable to unlock subnet {}", subnetId);
1214             throw new RuntimeException(String.format("Unable to unlock subnetId %s", subnetId), e.getCause());
1215         }
1216     }
1217
1218     static Optional<IpAddress> getGatewayIpAddressFromInterface(String srcInterface,
1219             INeutronVpnManager neutronVpnService, DataBroker dataBroker) {
1220         Optional <IpAddress> gatewayIp = Optional.absent();
1221         if (neutronVpnService != null) {
1222             //TODO(Gobinath): Need to fix this as assuming port will belong to only one Subnet would be incorrect"
1223             Port port = neutronVpnService.getNeutronPort(srcInterface);
1224             if (port != null && port.getFixedIps() != null && port.getFixedIps().get(0) != null && port.getFixedIps().get(0).getSubnetId() != null) {
1225                 gatewayIp = Optional.of(neutronVpnService.getNeutronSubnet(port.getFixedIps().get(0).getSubnetId()).getGatewayIp());
1226             }
1227         } else {
1228             LOG.debug("neutron vpn service is not configured");
1229         }
1230         return gatewayIp;
1231     }
1232
1233     static Optional<String> getGWMacAddressFromInterface(MacEntry macEntry, IpAddress gatewayIp,
1234             DataBroker dataBroker, OdlInterfaceRpcService interfaceRpc) {
1235         Optional <String> gatewayMac = Optional.absent();
1236         long vpnId = getVpnId(dataBroker, macEntry.getVpnName());
1237         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds>
1238         vpnIdsInstanceIdentifier = VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId);
1239         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds> vpnIdsOptional
1240         = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdsInstanceIdentifier);
1241         if (!vpnIdsOptional.isPresent()) {
1242             LOG.trace("VPN {} not configured", vpnId);
1243             return gatewayMac;
1244         }
1245         VpnPortipToPort vpnTargetIpToPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker,
1246                 macEntry.getVpnName(), gatewayIp.getIpv4Address().getValue());
1247         if (vpnTargetIpToPort != null && vpnTargetIpToPort.isSubnetIp()) {
1248             gatewayMac = Optional.of(vpnTargetIpToPort.getMacAddress());
1249         } else {
1250             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds vpnIds = vpnIdsOptional.get();
1251             if(vpnIds.isExternalVpn()) {
1252                 gatewayMac = InterfaceUtils.getMacAddressForInterface(dataBroker, macEntry.getInterfaceName());
1253             }
1254         }
1255         return gatewayMac;
1256     }
1257
1258     public static void runOnlyInLeaderNode(EntityOwnershipService entityOwnershipService, Runnable job) {
1259         runOnlyInLeaderNode(entityOwnershipService, job, "");
1260     }
1261
1262     public static void runOnlyInLeaderNode(EntityOwnershipService entityOwnershipService, final Runnable job,
1263             final String jobDescription) {
1264         ListenableFuture<Boolean> checkEntityOwnerFuture = ClusteringUtils.checkNodeEntityOwner(
1265                 entityOwnershipService, VpnConstants.ARP_MONITORING_ENTITY,
1266                 VpnConstants.ARP_MONITORING_ENTITY);
1267         Futures.addCallback(checkEntityOwnerFuture, new FutureCallback<Boolean>() {
1268             @Override
1269             public void onSuccess(Boolean isOwner) {
1270                 if (isOwner) {
1271                     job.run();
1272                 } else {
1273                     LOG.trace("job is not run as i m not cluster owner desc :{} ", jobDescription);
1274                 }
1275             }
1276
1277             @Override
1278             public void onFailure(Throwable error) {
1279                 LOG.error("Failed to identity cluster owner ", error);
1280             }
1281         });
1282     }
1283
1284     public static boolean isVpnIntfPresentInVpnToDpnList(DataBroker broker, VpnInterface vpnInterface) {
1285         BigInteger dpnId = vpnInterface.getDpnId();
1286         String rd = VpnUtil.getVpnRd(broker, vpnInterface.getVpnInstanceName());
1287         VpnInstanceOpDataEntry vpnInstanceOpData = VpnUtil.getVpnInstanceOpDataFromCache(broker, rd);
1288         if (vpnInstanceOpData != null) {
1289             List<VpnToDpnList> dpnToVpns = vpnInstanceOpData.getVpnToDpnList();
1290             if (dpnToVpns!= null) {
1291                 for (VpnToDpnList dpn :dpnToVpns) {
1292                     if (dpn.getDpnId().equals(dpnId)) {
1293                         if (dpn.getVpnInterfaces().contains(vpnInterface.getName())) {
1294                             return true;
1295                         } else {
1296                             return false;
1297                         }
1298                     }
1299                 }
1300             }
1301         }
1302         return false;
1303     }
1304
1305     public static void setupGwMacIfExternalVpn(DataBroker dataBroker, IMdsalApiManager mdsalManager, BigInteger dpnId, String interfaceName, long vpnId,
1306             WriteTransaction writeInvTxn, int addOrRemove) {
1307         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds> vpnIdsInstanceIdentifier =
1308                 getVpnIdToVpnInstanceIdentifier(vpnId);
1309         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds> vpnIdsOptional = read(dataBroker,
1310                 LogicalDatastoreType.CONFIGURATION, vpnIdsInstanceIdentifier);
1311         if (vpnIdsOptional.isPresent() && vpnIdsOptional.get().isExternalVpn()) {
1312             Optional<String> gwMacAddressOptional = InterfaceUtils.getMacAddressForInterface(dataBroker, interfaceName);
1313             if (!gwMacAddressOptional.isPresent()) {
1314                 LOG.error("Failed to get gwMacAddress for interface {}", interfaceName);
1315                 return;
1316             }
1317             String gwMacAddress = gwMacAddressOptional.get();
1318             FlowEntity flowEntity = VpnUtil.buildL3vpnGatewayFlow(dpnId, gwMacAddress, vpnId);
1319             if (addOrRemove == NwConstants.ADD_FLOW) {
1320                 mdsalManager.addFlowToTx(flowEntity, writeInvTxn);
1321             } else if (addOrRemove == NwConstants.DEL_FLOW) {
1322                 mdsalManager.removeFlowToTx(flowEntity, writeInvTxn);
1323             }
1324         }
1325     }
1326
1327     public static Optional<VpnPortipToPort> getRouterInterfaceForVpnInterface(DataBroker dataBroker,
1328                                                                               String interfaceName,
1329                                                                               String vpnName,
1330                                                                               Uuid subnetUuid) {
1331         Optional<VpnPortipToPort> gwPortOptional = Optional.absent();
1332         if (subnetUuid != null) {
1333             final Optional<String> gatewayIp = getVpnSubnetGatewayIp(dataBroker, subnetUuid);
1334             if (gatewayIp.isPresent()) {
1335                 String gwIp = gatewayIp.get();
1336                 gwPortOptional = Optional.fromNullable(getNeutronPortFromVpnPortFixedIp(dataBroker, vpnName, gwIp));
1337             }
1338         }
1339         return gwPortOptional;
1340     }
1341
1342     public static Optional<String> getVpnSubnetGatewayIp(DataBroker dataBroker, final Uuid subnetUuid) {
1343         Optional<String> gwIpAddress = Optional.absent();
1344         final SubnetKey subnetkey = new SubnetKey(subnetUuid);
1345         final InstanceIdentifier<Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class)
1346                 .child(Subnets.class)
1347                 .child(Subnet.class, subnetkey);
1348         final Optional<Subnet> subnet = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetidentifier);
1349         if (subnet.isPresent()) {
1350             Class<? extends IpVersionBase> ipVersionBase = subnet.get().getIpVersion();
1351             if (ipVersionBase.equals(IpVersionV4.class)) {
1352                 LOG.trace("Obtained subnet {} for vpn interface", subnet.get().getUuid().getValue());
1353                 gwIpAddress = Optional.of(subnet.get().getGatewayIp().getIpv4Address().getValue());
1354                 return gwIpAddress;
1355             }
1356         }
1357         return gwIpAddress;
1358     }
1359
1360     public static RouterToNaptSwitch getRouterToNaptSwitch(DataBroker dataBroker, String routerName) {
1361         InstanceIdentifier<RouterToNaptSwitch> id = InstanceIdentifier.builder(NaptSwitches.class)
1362                 .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
1363         Optional<RouterToNaptSwitch> routerToNaptSwitchData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
1364         return routerToNaptSwitchData.isPresent() ? routerToNaptSwitchData.get() : null;
1365     }
1366
1367     public static BigInteger getPrimarySwitchForRouter(DataBroker dataBroker, String routerName) {
1368         RouterToNaptSwitch routerToNaptSwitch = getRouterToNaptSwitch(dataBroker, routerName);
1369         return routerToNaptSwitch != null ? routerToNaptSwitch.getPrimarySwitchId() : null;
1370     }
1371
1372 }