Merge "Vpnmanager module sync up"
[netvirt.git] / vpnservice / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / netvirt / vpnmanager / VpnUtil.java
1 /*
2  * Copyright (c) 2015 - 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 java.math.BigInteger;
12 import java.net.InetAddress;
13 import java.util.*;
14 import java.util.concurrent.ExecutionException;
15 import java.util.concurrent.Future;
16
17 import com.google.common.base.Optional;
18 import com.google.common.base.Preconditions;
19 import com.google.common.primitives.Ints;
20 import com.google.common.util.concurrent.CheckedFuture;
21 import com.google.common.util.concurrent.FutureCallback;
22 import com.google.common.util.concurrent.Futures;
23
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
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.MDSALUtil;
30 import org.opendaylight.genius.mdsalutil.NwConstants;
31 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
32 import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
33 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
34 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
35 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
36 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
37 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
38 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
39 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
40 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
41 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanTagNameMap;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagName;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagNameKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.*;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIds;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIdsBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIdsKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterfaceBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterface;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterfaceKey;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.Vpn;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.VpnBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.VpnKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdPools;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPool;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPoolKey;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.IfIndexesInterfaceMap;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._if.indexes._interface.map.IfIndexInterface;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._if.indexes._interface.map.IfIndexInterfaceKey;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.L3nexthop;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthops;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthopsKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinkStates;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinks;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkState;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkStateKey;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
107 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
108 import org.opendaylight.yangtools.yang.common.RpcResult;
109 import org.opendaylight.yangtools.yang.binding.DataObject;
110 import org.opendaylight.yangtools.yang.data.impl.schema.tree.SchemaValidationFailedException;
111 import org.slf4j.Logger;
112 import org.slf4j.LoggerFactory;
113
114 public class VpnUtil {
115     private static final Logger LOG = LoggerFactory.getLogger(VpnUtil.class);
116     private static final int DEFAULT_PREFIX_LENGTH = 32;
117     private static final String PREFIX_SEPARATOR = "/";
118
119     static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
120         return InstanceIdentifier.builder(VpnInterfaces.class)
121                 .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build();
122     }
123
124     static InstanceIdentifier<VpnInstance> getVpnInstanceIdentifier(String vpnName) {
125         return InstanceIdentifier.builder(VpnInstances.class)
126                 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
127     }
128
129     static VpnInterface getVpnInterface(String intfName, String vpnName, Adjacencies aug, BigInteger dpnId, Boolean isSheduledForRemove) {
130         return new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(intfName)).setVpnInstanceName(vpnName).setDpnId(dpnId)
131                 .setScheduledForRemove(isSheduledForRemove).addAugmentation(Adjacencies.class, aug)
132                 .build();
133     }
134
135     static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
136         return InstanceIdentifier.builder(PrefixToInterface.class)
137                 .child(VpnIds.class, new VpnIdsKey(vpnId)).child(Prefixes.class,
138                         new PrefixesKey(ipPrefix)).build();
139     }
140
141     static InstanceIdentifier<VpnIds> getPrefixToInterfaceIdentifier(long vpnId) {
142         return InstanceIdentifier.builder(PrefixToInterface.class)
143                 .child(VpnIds.class, new VpnIdsKey(vpnId)).build();
144     }
145
146     static VpnIds getPrefixToInterface(long vpnId) {
147         return new VpnIdsBuilder().setKey(new VpnIdsKey(vpnId)).setVpnId(vpnId).build();
148     }
149
150     static Prefixes getPrefixToInterface(BigInteger dpId, String vpnInterfaceName, String ipPrefix) {
151         return new PrefixesBuilder().setDpnId(dpId).setVpnInterfaceName(
152                 vpnInterfaceName).setIpAddress(ipPrefix).build();
153     }
154
155     static InstanceIdentifier<Extraroute> getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) {
156         return InstanceIdentifier.builder(VpnToExtraroute.class)
157                 .child(Vpn.class, new VpnKey(vrfId)).child(Extraroute.class,
158                         new ExtrarouteKey(ipPrefix)).build();
159     }
160
161     static InstanceIdentifier<Vpn> getVpnToExtrarouteIdentifier(String vrfId) {
162         return InstanceIdentifier.builder(VpnToExtraroute.class)
163                 .child(Vpn.class, new VpnKey(vrfId)).build();
164     }
165
166     static Vpn getVpnToExtraRoute(String vrfId) {
167         return new VpnBuilder().setKey(new VpnKey(vrfId)).setVrfId(vrfId).build();
168     }
169
170     /**
171      * Retrieves the Instance Identifier that points to an InterVpnLink object
172      * in MDSL
173      *
174      * @param vpnLinkName The name of the InterVpnLink
175      * @return The requested InstanceIdentifier
176      */
177     public static InstanceIdentifier<InterVpnLinkState> getInterVpnLinkStateIid(String vpnLinkName) {
178         return InstanceIdentifier.builder(InterVpnLinkStates.class).child(InterVpnLinkState.class, new InterVpnLinkStateKey(vpnLinkName)).build();
179     }
180
181     /**
182      * Get inter-VPN link state
183      *
184      * @param broker dataBroker service reference
185      * @param vpnLinkName The name of the InterVpnLink
186      * @return the object that contains the State of the specified InterVpnLink
187      */
188     public static InterVpnLinkState getInterVpnLinkState(DataBroker broker, String vpnLinkName) {
189         InstanceIdentifier<InterVpnLinkState> vpnLinkStateIid = VpnUtil.getInterVpnLinkStateIid(vpnLinkName);
190         Optional<InterVpnLinkState> vpnLinkState = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
191                 vpnLinkStateIid);
192         if (vpnLinkState.isPresent()) {
193             return vpnLinkState.get();
194         }
195         return null;
196     }
197
198     /**
199      * Get VRF table given a Route Distinguisher
200      *
201      * @param broker dataBroker service reference
202      * @param rd Route-Distinguisher
203      * @return VrfTables that holds the list of VrfEntries of the specified rd
204      */
205     public static VrfTables getVrfTable(DataBroker broker, String rd) {
206         InstanceIdentifier<VrfTables> id =
207                 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
208         Optional<VrfTables> vrfTable = read(broker, LogicalDatastoreType.CONFIGURATION, id);
209         return vrfTable.isPresent() ? vrfTable.get() : null;
210     }
211
212     /**
213      * Retrieves the VrfEntries that belong to a given VPN filtered out by
214      * Origin, searching by its Route-Distinguisher
215      *
216      * @param broker dataBroker service reference
217      * @param rd     Route-distinguisher of the VPN
218      * @param originsToConsider Only entries whose origin is included in this
219      *     list will be considered
220      * @return the list of VrfEntries
221      */
222     public static List<VrfEntry> getVrfEntriesByOrigin(DataBroker broker, String rd,
223                                                        List<RouteOrigin> originsToConsider) {
224         List<VrfEntry> result = new ArrayList<VrfEntry>();
225         List<VrfEntry> allVpnVrfEntries = getAllVrfEntries(broker, rd);
226         for (VrfEntry vrfEntry : allVpnVrfEntries) {
227             if (originsToConsider.contains(RouteOrigin.value(vrfEntry.getOrigin()))) {
228                 result.add(vrfEntry);
229             }
230         }
231         return result;
232     }
233
234     static List<Prefixes> getAllPrefixesToInterface(DataBroker broker, long vpnId) {
235         Optional<VpnIds> vpnIds = read(broker, LogicalDatastoreType.OPERATIONAL, getPrefixToInterfaceIdentifier(vpnId));
236         if (vpnIds.isPresent()) {
237             return vpnIds.get().getPrefixes();
238         }
239         return new ArrayList<Prefixes>();
240     }
241
242     static List<Extraroute> getAllExtraRoutes(DataBroker broker, String vrfId) {
243         Optional<Vpn> extraRoutes = read(broker, LogicalDatastoreType.OPERATIONAL, getVpnToExtrarouteIdentifier(vrfId));
244         if (extraRoutes.isPresent()) {
245             return extraRoutes.get().getExtraroute();
246         }
247         return new ArrayList<Extraroute>();
248     }
249
250     /**
251      * Retrieves all the VrfEntries that belong to a given VPN searching by its
252      * Route-Distinguisher
253      *
254      * @param broker dataBroker service reference
255      * @param rd     Route-distinguisher of the VPN
256      * @return the list of VrfEntries
257      */
258     public static List<VrfEntry> getAllVrfEntries(DataBroker broker, String rd) {
259         VrfTables vrfTables = VpnUtil.getVrfTable(broker, rd);
260         return (vrfTables != null) ? vrfTables.getVrfEntry() : new ArrayList<VrfEntry>();
261     }
262
263     //FIXME: Implement caches for DS reads
264     static VpnInstance getVpnInstance(DataBroker broker, String vpnInstanceName) {
265         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class,
266                 new VpnInstanceKey(vpnInstanceName)).build();
267         Optional<VpnInstance> vpnInstance = read(broker, LogicalDatastoreType.CONFIGURATION, id);
268         return (vpnInstance.isPresent()) ? vpnInstance.get() : null;
269     }
270
271     static List<VpnInstance> getAllVpnInstance(DataBroker broker) {
272         InstanceIdentifier<VpnInstances> id = InstanceIdentifier.builder(VpnInstances.class).build();
273         Optional<VpnInstances> optVpnInstances = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
274         if (optVpnInstances.isPresent()) {
275             return optVpnInstances.get().getVpnInstance();
276         } else {
277             return new ArrayList<VpnInstance>();
278         }
279     }
280
281     static VrfEntry getVrfEntry(DataBroker broker, String rd, String ipPrefix) {
282
283         VrfTables vrfTable = getVrfTable(broker, rd);
284         // TODO: why check VrfTables if we later go for the specific VrfEntry?
285         if (vrfTable != null) {
286             InstanceIdentifier<VrfEntry> vrfEntryId =
287                     InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).
288                             child(VrfEntry.class, new VrfEntryKey(ipPrefix)).build();
289             Optional<VrfEntry> vrfEntry = read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
290             if (vrfEntry.isPresent()) {
291                 return (vrfEntry.get());
292             }
293         }
294         return null;
295     }
296
297     static List<Adjacency> getAdjacenciesForVpnInterfaceFromConfig(DataBroker broker, String intfName) {
298         final InstanceIdentifier<VpnInterface> identifier = getVpnInterfaceIdentifier(intfName);
299         InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
300         Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
301
302         if (adjacencies.isPresent()) {
303             List<Adjacency> nextHops = adjacencies.get().getAdjacency();
304             return nextHops;
305         }
306         return null;
307     }
308
309     static Extraroute getVpnToExtraroute(String ipPrefix, List<String> nextHopList) {
310         return new ExtrarouteBuilder().setPrefix(ipPrefix).setNexthopIpList(nextHopList).build();
311     }
312
313     public static List<Extraroute> getVpnExtraroutes(DataBroker broker, String vpnRd) {
314         InstanceIdentifier<Vpn> vpnExtraRoutesId =
315                 InstanceIdentifier.builder(VpnToExtraroute.class).child(Vpn.class, new VpnKey(vpnRd)).build();
316         Optional<Vpn> vpnOpc = read(broker, LogicalDatastoreType.OPERATIONAL, vpnExtraRoutesId);
317         return vpnOpc.isPresent() ? vpnOpc.get().getExtraroute() : new ArrayList<Extraroute>();
318     }
319
320     static Adjacencies getVpnInterfaceAugmentation(List<Adjacency> nextHopList) {
321         return new AdjacenciesBuilder().setAdjacency(nextHopList).build();
322     }
323
324     public static InstanceIdentifier<IdPool> getPoolId(String poolName) {
325         InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
326                 InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName));
327         InstanceIdentifier<IdPool> id = idBuilder.build();
328         return id;
329     }
330
331     static InstanceIdentifier<VpnInterfaces> getVpnInterfacesIdentifier() {
332         return InstanceIdentifier.builder(VpnInterfaces.class).build();
333     }
334
335     static InstanceIdentifier<Interface> getInterfaceIdentifier(String interfaceName) {
336         return InstanceIdentifier.builder(Interfaces.class)
337                 .child(Interface.class, new InterfaceKey(interfaceName)).build();
338     }
339
340     static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
341         return InstanceIdentifier.builder(VpnInstanceOpData.class)
342                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd))
343                 .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
344     }
345
346     public static BigInteger getCookieArpFlow(int interfaceTag) {
347         return VpnConstants.COOKIE_L3_BASE.add(new BigInteger("0110000", 16)).add(
348                 BigInteger.valueOf(interfaceTag));
349     }
350
351     public static BigInteger getCookieL3(int vpnId) {
352         return VpnConstants.COOKIE_L3_BASE.add(new BigInteger("0610000", 16)).add(BigInteger.valueOf(vpnId));
353     }
354
355     public static String getFlowRef(BigInteger dpnId, short tableId, int ethType, int lPortTag, int arpType) {
356         return new StringBuffer().append(VpnConstants.FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
357                 .append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(ethType).append(lPortTag)
358                 .append(NwConstants.FLOWID_SEPARATOR).append(arpType).toString();
359     }
360
361     public static int getUniqueId(IdManagerService idManager, String poolName, String idKey) {
362         AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
363
364         try {
365             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
366             RpcResult<AllocateIdOutput> rpcResult = result.get();
367             if (rpcResult.isSuccessful()) {
368                 return rpcResult.getResult().getIdValue().intValue();
369             } else {
370                 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
371             }
372         } catch (InterruptedException | ExecutionException e) {
373             LOG.warn("Exception when getting Unique Id", e);
374         }
375         return 0;
376     }
377
378     public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
379         ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
380         try {
381             Future<RpcResult<Void>> result = idManager.releaseId(idInput);
382             RpcResult<Void> rpcResult = result.get();
383             if (!rpcResult.isSuccessful()) {
384                 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
385             }
386         } catch (InterruptedException | ExecutionException e) {
387             LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
388         }
389     }
390
391     public static String getNextHopLabelKey(String rd, String prefix) {
392         return rd + VpnConstants.SEPARATOR + prefix;
393     }
394
395     /**
396      * Retrieves the VpnInstance name (typically the VPN Uuid) out from the
397      * route-distinguisher
398      *
399      * @param broker dataBroker service reference
400      * @param rd Route-Distinguisher
401      * @return the VpnInstance name
402      */
403     public static String getVpnNameFromRd(DataBroker broker, String rd) {
404         VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(broker, rd);
405         return (vpnInstanceOpData != null) ? vpnInstanceOpData.getVpnInstanceName() : null;
406     }
407
408     /**
409      * Retrieves the dataplane identifier of a specific VPN, searching by its
410      * VpnInstance name.
411      *
412      * @param broker dataBroker service reference
413      * @param vpnName Name of the VPN
414      * @return the dataplane identifier of the VPN, the VrfTag.
415      */
416     public static long getVpnId(DataBroker broker, String vpnName) {
417
418         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
419                 = getVpnInstanceToVpnIdIdentifier(vpnName);
420         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
421                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
422
423         long vpnId = VpnConstants.INVALID_ID;
424         if (vpnInstance.isPresent()) {
425             vpnId = vpnInstance.get().getVpnId();
426         }
427         return vpnId;
428     }
429
430     /**
431      * Retrieves the VPN Route Distinguisher searching by its Vpn instance name
432      *
433      * @param broker dataBroker service reference
434      * @param vpnName Name of the VPN
435      * @return the route-distinguisher of the VPN
436      */
437     public static String getVpnRd(DataBroker broker, String vpnName) {
438         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
439                 = getVpnInstanceToVpnIdIdentifier(vpnName);
440         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
441                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
442
443         String rd = null;
444         if (vpnInstance.isPresent()) {
445             rd = vpnInstance.get().getVrfId();
446         }
447         return rd;
448     }
449
450     /**
451      * Get VPN Route Distinguisher from VPN Instance Configuration
452      *
453      * @param broker dataBroker service reference
454      * @param vpnName Name of the VPN
455      * @return the route-distinguisher of the VPN
456      */
457     public static String getVpnRdFromVpnInstanceConfig(DataBroker broker, String vpnName) {
458         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
459                 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
460         Optional<VpnInstance> vpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
461         String rd = null;
462         if (vpnInstance.isPresent()) {
463             VpnInstance instance = vpnInstance.get();
464             VpnAfConfig config = instance.getIpv4Family();
465             rd = config.getRouteDistinguisher();
466         }
467         return rd;
468     }
469
470     /**
471      * Writes in MDSAL a new VrfEntry for a VPN specified by its Route-Distinguisher. It performs a merge,
472      * that is, if the VrfEntry exists the nexthop is added the VrfEntry nexthop list. If the entry does not
473      * exist, it is created.
474      *
475      * @param broker dataBroker service reference
476      * @param rd Route-distinguisher of the VPN
477      * @param prefix Destination of the route. This, together with the RD, identifies the VrfEntry
478      * @param nextHop Nexthop of the route
479      * @param label Label of the route
480      */
481     public static void addFibEntryToDS(DataBroker broker, String rd, String prefix, String nextHop, int label, RouteOrigin origin) {
482         Preconditions.checkNotNull(rd, "RD cannot be null");
483         LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nextHop, label);
484         synchronized (rd.intern()) {
485             InstanceIdentifier<VrfTables> vrfTableId =
486                     InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
487             VrfEntry vrfEntry = getVrfEntry(broker, rd, prefix);
488             if (vrfEntry != null) {
489                 List<String> nextHopList = vrfEntry.getNextHopAddressList();
490                 nextHopList.add(nextHop);
491                 VrfEntryBuilder builder = new VrfEntryBuilder(vrfEntry).setNextHopAddressList(nextHopList);
492                 VrfEntry newVrfEntry = builder.build();
493                 // Just update the VrfEntry
494                 VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION,
495                         vrfTableId.child(VrfEntry.class, new VrfEntryKey(prefix)), newVrfEntry);
496             } else {
497                 List<VrfEntry> currentVrfEntries = new ArrayList<VrfEntry>();
498                 VrfEntryBuilder builder = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
499                         .setLabel((long) label).setOrigin(origin.getValue());
500                 vrfEntry = builder.build();
501                 currentVrfEntries.add(vrfEntry);
502                 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(
503                         currentVrfEntries).build();
504                 VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
505             }
506             LOG.info("ADD: Added Fib Entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHop, label);
507         }
508
509     }
510
511     /**
512      * Removes a specific Nexthop from a VrfEntry. If Nexthop to remove is the
513      * last one in the VrfEntry, then the VrfEntry is removed too.
514      *
515      * @param broker dataBroker service reference
516      * @param rd Route-Distinguisher to which the VrfEntry belongs to
517      * @param prefix Destination of the route
518      * @param nextHopToRemove Specific nexthop within the Route to be removed.
519      *           If null or empty, then the whole VrfEntry is removed
520      */
521     public static void removeFibEntryFromDS(DataBroker broker, String rd, String prefix, String nextHopToRemove) {
522
523         LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
524
525         // Looking for existing prefix in MDSAL database
526         InstanceIdentifier<VrfEntry> vrfEntryId =
527             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
528                                                         .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
529         Optional<VrfEntry> entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
530
531         if ( entry.isPresent() ) {
532             synchronized (rd.intern()) {
533                 List<String> nhListRead = new ArrayList<>();
534                 if ( nextHopToRemove != null && !nextHopToRemove.isEmpty()) {
535                     nhListRead = entry.get().getNextHopAddressList();
536                     if (nhListRead.contains(nextHopToRemove)) {
537                         nhListRead.remove(nextHopToRemove);
538                     }
539                 }
540
541                 if (nhListRead.isEmpty()) {
542                     // Remove the whole entry
543                     MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
544                     LOG.info("Removed Fib Entry rd {} prefix {}", rd, prefix);
545                 } else {
546                     // An update must be done, not including the current next hop
547                     VrfEntry vrfEntry =
548                         new VrfEntryBuilder(entry.get()).setDestPrefix(prefix).setNextHopAddressList(nhListRead)
549                                                         .setKey(new VrfEntryKey(prefix)).build();
550                     MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
551                     MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
552                     LOG.info("Removed Nexthop {} from Fib Entry rd {} prefix {}", nextHopToRemove, rd, prefix);
553                 }
554             }
555         } else {
556             LOG.warn("Could not find VrfEntry for Route-Distinguisher={} and prefix={}", rd, prefix);
557         }
558     }
559
560
561     /**
562      * Remove from MDSAL all those VrfEntries in a VPN that have an specific RouteOrigin
563      *
564      * @param broker dataBroker service reference
565      * @param rd     Route Distinguisher
566      * @param origin Origin of the Routes to be removed (see {@link org.opendaylight.netvirt.bgpmanager.api.RouteOrigin})
567      */
568     public static void removeVrfEntriesByOrigin(DataBroker broker, String rd, RouteOrigin origin) {
569         InstanceIdentifier<VrfTables> vpnVrfTableIid =
570                 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
571         Optional<VrfTables> vrfTablesOpc = read(broker, LogicalDatastoreType.CONFIGURATION, vpnVrfTableIid);
572         if (vrfTablesOpc.isPresent()) {
573             VrfTables vrfTables = vrfTablesOpc.get();
574             List<VrfEntry> newVrfEntries = new ArrayList<VrfEntry>();
575             for (VrfEntry vrfEntry : vrfTables.getVrfEntry()) {
576                 if (origin == RouteOrigin.value(vrfEntry.getOrigin())) {
577                     delete(broker, LogicalDatastoreType.CONFIGURATION, vpnVrfTableIid.child(VrfEntry.class,
578                             vrfEntry.getKey()));
579                 }
580             }
581         }
582     }
583
584     public static void removeVrfEntriesByNexthop(DataBroker broker, String rd, String nexthop) {
585         InstanceIdentifier<VrfTables> vpnVrfTableIid =
586                 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
587         Optional<VrfTables> vrfTablesOpc = read(broker, LogicalDatastoreType.CONFIGURATION, vpnVrfTableIid);
588         if (vrfTablesOpc.isPresent()) {
589             VrfTables vrfTables = vrfTablesOpc.get();
590             for (VrfEntry vrfEntry : vrfTables.getVrfEntry()) {
591                 if (vrfEntry.getNextHopAddressList() != null && vrfEntry.getNextHopAddressList().contains(nexthop)) {
592                     // TODO: Removes all the VrfEntry if one of the nexthops is the specified nexthop
593                     //                should we only remove the specific nexthop, or all the VrfEnry?
594                     delete(broker, LogicalDatastoreType.CONFIGURATION, vpnVrfTableIid.child(VrfEntry.class,
595                             vrfEntry.getKey()));
596                 }
597             }
598         }
599     }
600
601     static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
602                 getVpnInstanceToVpnId(String vpnName, long vpnId, String rd) {
603
604         return new VpnInstanceBuilder().setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).build();
605
606     }
607
608     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
609                 getVpnInstanceToVpnIdIdentifier(String vpnName) {
610         return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
611                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
612                         new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
613     }
614
615     static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds
616                 getVpnIdToVpnInstance(long vpnId, String vpnName, String rd, boolean isExternalVpn) {
617         return new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsBuilder()
618                 .setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).setExternalVpn(isExternalVpn).build();
619
620     }
621
622     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds>
623         getVpnIdToVpnInstanceIdentifier(long vpnId) {
624         return InstanceIdentifier.builder(VpnIdToVpnInstance.class)
625                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds.class,
626                         new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsKey(Long.valueOf(vpnId))).build();
627     }
628
629     /**
630      * Retrieves the Vpn Name searching by its VPN Tag.
631      *
632      * @param broker dataBroker service reference
633      * @param vpnId Dataplane identifier of the VPN
634      * @return the Vpn instance name
635      */
636     public static String getVpnName(DataBroker broker, long vpnId) {
637
638         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds> id
639                 = getVpnIdToVpnInstanceIdentifier(vpnId);
640         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds> vpnInstance
641                 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
642
643         String vpnName = null;
644         if (vpnInstance.isPresent()) {
645             vpnName = vpnInstance.get().getVpnInstanceName();
646         }
647         return vpnName;
648     }
649
650     public static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
651         return InstanceIdentifier.builder(VpnInstanceOpData.class)
652                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
653     }
654
655     static VpnInstanceOpDataEntry getVpnInstanceOpDataBuilder(String rd, long vpnId, String vpnName) {
656         return new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnName).build();
657     }
658
659     static VpnInstanceOpDataEntry updateIntfCntInVpnInstOpData(Long newCount, String vrfId) {
660         return new VpnInstanceOpDataEntryBuilder().setVpnInterfaceCount(newCount).setVrfId(vrfId).build();
661     }
662
663     static InstanceIdentifier<RouterInterface> getRouterInterfaceId(String interfaceName) {
664         return InstanceIdentifier.builder(RouterInterfaces.class)
665                 .child(RouterInterface.class, new RouterInterfaceKey(interfaceName)).build();
666     }
667
668     static RouterInterface getRouterInterface(String interfaceName, String routerName) {
669         return new RouterInterfaceBuilder().setKey(new RouterInterfaceKey(interfaceName))
670                 .setInterfaceName(interfaceName).setRouterName(routerName).build();
671     }
672
673     static VpnInstanceOpDataEntry getVpnInstanceOpData(DataBroker broker, String rd) {
674         InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
675         Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(broker, LogicalDatastoreType.OPERATIONAL, id);
676         if (vpnInstanceOpData.isPresent()) {
677             return vpnInstanceOpData.get();
678         }
679         return null;
680     }
681
682     static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
683         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
684         Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
685
686         if (configuredVpnInterface.isPresent()) {
687             return configuredVpnInterface.get();
688         }
689         return null;
690     }
691
692     static VpnInterface getOperationalVpnInterface(DataBroker broker, String interfaceName) {
693         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
694         Optional<VpnInterface> operationalVpnInterface = read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
695
696         if (operationalVpnInterface.isPresent()) {
697             return operationalVpnInterface.get();
698         }
699         return null;
700     }
701
702     static boolean isVpnInterfaceConfigured(DataBroker broker, String interfaceName) {
703         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
704         Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
705
706         if (configuredVpnInterface.isPresent()) {
707             return true;
708         }
709         return false;
710     }
711
712     static String getIpPrefix(String prefix) {
713         String prefixValues[] = prefix.split("/");
714         if (prefixValues.length == 1) {
715             prefix = prefix + PREFIX_SEPARATOR + DEFAULT_PREFIX_LENGTH;
716         }
717         return prefix;
718     }
719
720     static final FutureCallback<Void> DEFAULT_CALLBACK =
721             new FutureCallback<Void>() {
722                 @Override
723                 public void onSuccess(Void result) {
724                     LOG.debug("Success in Datastore operation");
725                 }
726
727                 @Override
728                 public void onFailure(Throwable error) {
729                     LOG.error("Error in Datastore operation", error);
730                 }
731
732                 ;
733             };
734
735     public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
736                                                           InstanceIdentifier<T> path) {
737
738         ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
739
740         Optional<T> result = Optional.absent();
741         try {
742             result = tx.read(datastoreType, path).get();
743         } catch (Exception e) {
744             throw new RuntimeException(e);
745         } finally {
746             tx.close();
747         }
748
749         return result;
750     }
751
752     public static <T extends DataObject> void asyncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
753                                                           InstanceIdentifier<T> path, T data) {
754         asyncUpdate(broker, datastoreType, path, data, DEFAULT_CALLBACK);
755     }
756
757     public static <T extends DataObject> void asyncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
758                                                           InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
759         WriteTransaction tx = broker.newWriteOnlyTransaction();
760         tx.merge(datastoreType, path, data, true);
761         Futures.addCallback(tx.submit(), callback);
762     }
763
764     public static <T extends DataObject> void asyncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
765                                                          InstanceIdentifier<T> path, T data) {
766         asyncWrite(broker, datastoreType, path, data, DEFAULT_CALLBACK);
767     }
768
769     public static <T extends DataObject> void asyncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
770                                                          InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
771         WriteTransaction tx = broker.newWriteOnlyTransaction();
772         tx.put(datastoreType, path, data, true);
773         Futures.addCallback(tx.submit(), callback);
774     }
775
776     public static <T extends DataObject> void tryDelete(DataBroker broker, LogicalDatastoreType datastoreType,
777                                                      InstanceIdentifier<T> path) {
778         try {
779             delete(broker, datastoreType, path, DEFAULT_CALLBACK);
780         } catch ( SchemaValidationFailedException sve ) {
781             LOG.info("Could not delete {}. SchemaValidationFailedException: {}", path, sve.getMessage());
782         } catch ( Exception e) {
783             LOG.info("Could not delete {}. Unhandled error: {}", path, e.getMessage());
784         }
785     }
786
787     public static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
788                                                      InstanceIdentifier<T> path) {
789         delete(broker, datastoreType, path, DEFAULT_CALLBACK);
790     }
791
792
793     public static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
794                                                      InstanceIdentifier<T> path, FutureCallback<Void> callback) {
795         WriteTransaction tx = broker.newWriteOnlyTransaction();
796         tx.delete(datastoreType, path);
797         Futures.addCallback(tx.submit(), callback);
798     }
799
800     public static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
801                                                         InstanceIdentifier<T> path, T data) {
802         WriteTransaction tx = broker.newWriteOnlyTransaction();
803         tx.put(datastoreType, path, data, true);
804         CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
805         try {
806             futures.get();
807         } catch (InterruptedException | ExecutionException e) {
808             LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
809             throw new RuntimeException(e.getMessage());
810         }
811     }
812
813     public static <T extends DataObject> void syncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
814                                                          InstanceIdentifier<T> path, T data) {
815         WriteTransaction tx = broker.newWriteOnlyTransaction();
816         tx.merge(datastoreType, path, data, true);
817         CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
818         try {
819             futures.get();
820         } catch (InterruptedException | ExecutionException e) {
821             LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
822             throw new RuntimeException(e.getMessage());
823         }
824     }
825
826     public static long getRemoteBCGroup(long elanTag) {
827         return VpnConstants.ELAN_GID_MIN + ((elanTag % VpnConstants.ELAN_GID_MIN) * 2);
828     }
829
830     // interface-index-tag operational container
831     public static IfIndexInterface getInterfaceInfoByInterfaceTag(DataBroker broker, long interfaceTag) {
832         InstanceIdentifier<IfIndexInterface> interfaceId = getInterfaceInfoEntriesOperationalDataPath(interfaceTag);
833         Optional<IfIndexInterface> existingInterfaceInfo = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
834         if (existingInterfaceInfo.isPresent()) {
835             return existingInterfaceInfo.get();
836         }
837         return null;
838     }
839
840     private static InstanceIdentifier<IfIndexInterface> getInterfaceInfoEntriesOperationalDataPath(long interfaceTag) {
841         return InstanceIdentifier.builder(IfIndexesInterfaceMap.class).child(IfIndexInterface.class,
842                 new IfIndexInterfaceKey((int) interfaceTag)).build();
843     }
844
845     public static ElanTagName getElanInfoByElanTag(DataBroker broker, long elanTag) {
846         InstanceIdentifier<ElanTagName> elanId = getElanInfoEntriesOperationalDataPath(elanTag);
847         Optional<ElanTagName> existingElanInfo = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, elanId);
848         if (existingElanInfo.isPresent()) {
849             return existingElanInfo.get();
850         }
851         return null;
852     }
853
854     private static InstanceIdentifier<ElanTagName> getElanInfoEntriesOperationalDataPath(long elanTag) {
855         return InstanceIdentifier.builder(ElanTagNameMap.class).child(ElanTagName.class,
856                 new ElanTagNameKey(elanTag)).build();
857     }
858
859
860     // TODO: Move this to NwUtil
861     public static boolean isIpInSubnet(int ipAddress, String subnetCidr) {
862         String[] subSplit = subnetCidr.split("/");
863         if (subSplit.length < 2) {
864             return false;
865         }
866
867         String subnetStr = subSplit[0];
868         int subnet = 0;
869         try {
870             InetAddress subnetAddress = InetAddress.getByName(subnetStr);
871             subnet = Ints.fromByteArray(subnetAddress.getAddress());
872         } catch (Exception ex) {
873             LOG.error("Passed in Subnet IP string not convertible to InetAdddress " + subnetStr);
874             return false;
875         }
876         int prefixLength = Integer.valueOf(subSplit[1]);
877         int mask = -1 << (32 - prefixLength);
878         if ((subnet & mask) == (ipAddress & mask)) {
879             return true;
880         }
881         return false;
882     }
883
884     /**
885      * Returns the Path identifier to reach a specific interface in a specific DPN in a given VpnInstance
886      *
887      * @param vpnRd     Route-Distinguisher of the VpnInstance
888      * @param dpnId     Id of the DPN where the interface is
889      * @param ifaceName Interface name
890      * @return the Instance Identifier
891      */
892     public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
893             .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces>
894     getVpnToDpnInterfacePath(String vpnRd, BigInteger dpnId, String ifaceName) {
895
896         return
897                 InstanceIdentifier.builder(VpnInstanceOpData.class)
898                         .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vpnRd))
899                         .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId))
900                         .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
901                                 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
902                                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
903                                         .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey(ifaceName))
904                         .build();
905     }
906
907     /**
908      * Includes a DPN with the corresponding interface names in the VpnToDpn operational data.
909      * This method is preferably over mergeDpnInVpnToDpnMap(DataBroker, String, String, BigInteger, List)
910      * when there are several DPNs to be merged since it saves some readings from MDSAL.
911      *
912      * @param broker     dataBroker service reference
913      * @param vpnOpData  Reference to the object that holds the Operational data of the VpnInstance
914      * @param dpnId      Id of the DPN where the interfaces to be added to Operational data are located
915      * @param ifaceNames List of interface names
916      */
917     public static void mergeDpnInVpnToDpnMap(DataBroker broker, VpnInstanceOpDataEntry vpnOpData, BigInteger dpnId,
918                                              List<String> ifaceNames) {
919         Preconditions.checkNotNull(vpnOpData);
920         Preconditions.checkNotNull(ifaceNames);
921
922         for (String ifaceName : ifaceNames) {
923             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
924                     .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnDpnIfaceIid =
925                     getVpnToDpnInterfacePath(vpnOpData.getKey().getVrfId(), dpnId, ifaceName);
926
927             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
928                     .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnDpnIface =
929                     new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
930                             .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list
931                             .VpnInterfacesBuilder().setKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
932                             .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey(ifaceName))
933                             .setInterfaceName(ifaceName)
934                             .build();
935
936             syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, vpnDpnIfaceIid, vpnDpnIface);
937         }
938     }
939
940     /**
941      * Includes a DPN with the corresponding interface names in the VpnToDpn operational data.
942      *
943      * @param broker dataBroker service reference
944      * @param vpnName Name of the VPN
945      * @param rd Route-Distinguisher
946      * @param dpnId Id of the DPN that includes the list of Ifaces to be
947      *           included in the Map
948      * @param ifaceNames List of interfaces to be included in the Map
949      */
950     public static void mergeDpnInVpnToDpnMap(DataBroker broker, String vpnName, String rd, BigInteger dpnId,
951                                              List<String> ifaceNames) {
952         InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
953                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vpnName))
954                 .build();
955
956         Optional<VpnInstanceOpDataEntry> vpnInstanceOpData =
957             MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
958         if (vpnInstanceOpData.isPresent()) {
959             mergeDpnInVpnToDpnMap(broker, vpnInstanceOpData.get(), dpnId, ifaceNames);
960         }
961     }
962
963     /**
964      * Removes a specific interface from the VpnToDpn operative map.
965      *
966      * @param broker    dataBroker service reference
967      * @param rd        Route-distinguisher of the VPN
968      * @param dpnId     Id of the DPN where the interface is
969      * @param ifaceName interface name.
970      */
971     public static void removeIfaceFromVpnToDpnMap(DataBroker broker, String rd, BigInteger dpnId, String ifaceName) {
972         tryDelete(broker, LogicalDatastoreType.CONFIGURATION, getVpnToDpnInterfacePath(rd, dpnId, ifaceName));
973         // Note: tryDelete is a best-effort. Sometimes we want to update the VpnToDpnMap ifaces when the
974         // DPN has gone down (and the VpnToDpnMap has been removed in a different Thread)
975     }
976
977     public static void removePrefixToInterfaceForVpnId(DataBroker broker, long vpnId) {
978         try {
979             // Clean up PrefixToInterface Operational DS
980             delete(broker, LogicalDatastoreType.OPERATIONAL,
981                     InstanceIdentifier.builder(PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId)).build(),
982                     DEFAULT_CALLBACK);
983         } catch (Exception e) {
984             LOG.error("Exception during cleanup of PrefixToInterface for VPN ID {}", vpnId, e);
985         }
986     }
987
988     public static void removeVpnExtraRouteForVpn(DataBroker broker, String vpnName) {
989         try {
990             // Clean up VPNExtraRoutes Operational DS
991             delete(broker, LogicalDatastoreType.OPERATIONAL,
992                     InstanceIdentifier.builder(VpnToExtraroute.class).child(Vpn.class, new VpnKey(vpnName)).build(),
993                     DEFAULT_CALLBACK);
994         } catch (Exception e) {
995             LOG.error("Exception during cleanup of VPNToExtraRoute for VPN {}", vpnName, e);
996         }
997     }
998
999     public static void removeVpnOpInstance(DataBroker broker, String vpnName) {
1000         try {
1001             // Clean up VPNInstanceOpDataEntry
1002             delete(broker, LogicalDatastoreType.OPERATIONAL, getVpnInstanceOpDataIdentifier(vpnName),
1003                     DEFAULT_CALLBACK);
1004         } catch (Exception e) {
1005             LOG.error("Exception during cleanup of VPNInstanceOpDataEntry for VPN {}", vpnName, e);
1006         }
1007     }
1008
1009     public static void removeVpnInstanceToVpnId(DataBroker broker, String vpnName) {
1010         try {
1011             delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnInstanceToVpnIdIdentifier(vpnName),
1012                     DEFAULT_CALLBACK);
1013         } catch (Exception e) {
1014             LOG.error("Exception during clean up of VpnInstanceToVpnId for VPN {}", vpnName, e);
1015         }
1016     }
1017
1018     public static void removeVpnIdToVpnInstance(DataBroker broker, long vpnId) {
1019         try {
1020             delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnIdToVpnInstanceIdentifier(vpnId),
1021                     DEFAULT_CALLBACK);
1022         } catch (Exception e) {
1023             LOG.error("Exception during clean up of VpnIdToVpnInstance for VPNID {}", vpnId, e);
1024         }
1025     }
1026
1027     public static void removeVrfTableForVpn(DataBroker broker, String vpnName) {
1028         // Clean up FIB Entries Config DS
1029         try {
1030             delete(broker, LogicalDatastoreType.CONFIGURATION,
1031                     InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(vpnName)).build(),
1032                     DEFAULT_CALLBACK);
1033         } catch (Exception e) {
1034             LOG.error("Exception during clean up of VrfTable from FIB for VPN {}", vpnName, e);
1035         }
1036     }
1037
1038     public static void removeL3nexthopForVpnId(DataBroker broker, long vpnId) {
1039         try {
1040             // Clean up L3NextHop Operational DS
1041             delete(broker, LogicalDatastoreType.OPERATIONAL,
1042                     InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).build(),
1043                     DEFAULT_CALLBACK);
1044         } catch (Exception e) {
1045             LOG.error("Exception during cleanup of L3NextHop for VPN ID {}", vpnId, e);
1046         }
1047     }
1048
1049     /**
1050      * Retrieves all configured InterVpnLinks
1051      *
1052      * @param broker dataBroker service reference
1053      * @return the list of InterVpnLinks
1054      */
1055     public static List<InterVpnLink> getAllInterVpnLinks(DataBroker broker) {
1056         InstanceIdentifier<InterVpnLinks> interVpnLinksIid = InstanceIdentifier.builder(InterVpnLinks.class).build();
1057
1058         Optional<InterVpnLinks> interVpnLinksOpData = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
1059                 interVpnLinksIid);
1060
1061         return (interVpnLinksOpData.isPresent()) ? interVpnLinksOpData.get().getInterVpnLink()
1062                 : new ArrayList<InterVpnLink>();
1063     }
1064
1065     /**
1066      * Retrieves the list of DPNs where the endpoint of a VPN in an InterVPNLink was instantiated
1067      *
1068      * @param broker dataBroker service reference
1069      * @param vpnLinkName the name of the InterVpnLink
1070      * @param vpnUuid UUID of the VPN whose endpoint to be checked
1071      * @return the list of DPN Ids
1072      */
1073     public static List<BigInteger> getVpnLinkEndpointDPNs(DataBroker broker, String vpnLinkName, String vpnUuid) {
1074         InterVpnLinkState interVpnLinkState = getInterVpnLinkState(broker, vpnLinkName);
1075         if (interVpnLinkState.getFirstEndpointState().getVpnUuid().getValue().equals(vpnUuid)) {
1076             return interVpnLinkState.getFirstEndpointState().getDpId();
1077         } else {
1078             return interVpnLinkState.getSecondEndpointState().getDpId();
1079         }
1080     }
1081
1082     /**
1083      * Retrieves an InterVpnLink by searching by one of its endpoint's IP.
1084      *
1085      * @param broker dataBroker service reference
1086      * @param endpointIp IP to serch for.
1087      * @return the InterVpnLink or null if no InterVpnLink can be found
1088      */
1089     public static InterVpnLink getInterVpnLinkByEndpointIp(DataBroker broker, String endpointIp) {
1090         List<InterVpnLink> allInterVpnLinks = getAllInterVpnLinks(broker);
1091         for (InterVpnLink interVpnLink : allInterVpnLinks) {
1092             if (interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(endpointIp)
1093                     || interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(endpointIp)) {
1094                 return interVpnLink;
1095             }
1096         }
1097         return null;
1098     }
1099
1100     /**
1101      * Retrieves the InterVpnLink that has one of its 2 endpoints installed in
1102      * the specified DpnId
1103      *
1104      * @param broker dataBroker service reference
1105      * @param dpnId Id of the DPN
1106      * @return The InterVpnLink object if found, Optional.absent() otherwise
1107      */
1108     public static Optional<InterVpnLink> getInterVpnLinkByDpnId(DataBroker broker, BigInteger dpnId) {
1109         List<InterVpnLink> allInterVpnLinks = getAllInterVpnLinks(broker);
1110         for (InterVpnLink interVpnLink : allInterVpnLinks) {
1111             InterVpnLinkState interVpnLinkState = getInterVpnLinkState(broker, interVpnLink.getName());
1112             if ( ( interVpnLinkState != null )
1113                  && ( interVpnLinkState.getFirstEndpointState().getDpId().contains(dpnId)
1114                       || interVpnLinkState.getSecondEndpointState().getDpId().contains(dpnId) ) ) {
1115                 return Optional.fromNullable(interVpnLink);
1116             }
1117         }
1118         return Optional.absent();
1119     }
1120
1121     /**
1122      * Leaks a route from one VPN to another. By default, the origin for this leaked route is INTERVPN
1123      *
1124      * @param broker           dataBroker service reference
1125      * @param bgpManager       Used to advertise routes to the BGP Router
1126      * @param interVpnLink     Reference to the object that holds the info about the link between the 2 VPNs
1127      * @param srcVpnUuid       UUID of the VPN that has the route that is going to be leaked to the other VPN
1128      * @param dstVpnUuid       UUID of the VPN that is going to receive the route
1129      * @param prefix           Prefix of the route
1130      * @param label            Label of the route in the original VPN
1131      */
1132     public static void leakRoute(DataBroker broker, IBgpManager bgpManager, InterVpnLink interVpnLink,
1133                                  String srcVpnUuid, String dstVpnUuid, String prefix, Long label) {
1134         leakRoute(broker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, prefix, label, RouteOrigin.INTERVPN);
1135     }
1136
1137     /**
1138      * Leaks a route from one VPN to another.
1139      *
1140      * @param broker           dataBroker service reference
1141      * @param bgpManager       Used to advertise routes to the BGP Router
1142      * @param interVpnLink     Reference to the object that holds the info about the link between the 2 VPNs
1143      * @param srcVpnUuid       UUID of the VPN that has the route that is going to be leaked to the other VPN
1144      * @param dstVpnUuid       UUID of the VPN that is going to receive the route
1145      * @param prefix           Prefix of the route
1146      * @param label            Label of the route in the original VPN
1147      * @param forcedOrigin     By default, origin for leaked routes should be INTERVPN, however it is possible to
1148      *                         provide a different origin if desired.
1149      */
1150     public static void leakRoute(DataBroker broker, IBgpManager bgpManager, InterVpnLink interVpnLink,
1151                                  String srcVpnUuid, String dstVpnUuid, String prefix, Long label,
1152                                  RouteOrigin forcedOrigin) {
1153         Preconditions.checkNotNull(interVpnLink);
1154
1155         // The source VPN must participate in the InterVpnLink
1156         Preconditions.checkArgument(interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(srcVpnUuid)
1157                         || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(srcVpnUuid),
1158                 "The source VPN {} does not participate in the interVpnLink {}",
1159                 srcVpnUuid, interVpnLink.getName());
1160         // The destination VPN must participate in the InterVpnLink
1161         Preconditions.checkArgument(interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(dstVpnUuid)
1162                         || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(dstVpnUuid),
1163                 "The destination VPN {} does not participate in the interVpnLink {}",
1164                 dstVpnUuid, interVpnLink.getName());
1165
1166         boolean destinationIs1stEndpoint = interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(dstVpnUuid);
1167
1168         String endpointIp = (destinationIs1stEndpoint) ? interVpnLink.getSecondEndpoint().getIpAddress().getValue()
1169                 : interVpnLink.getFirstEndpoint().getIpAddress().getValue();
1170
1171         VrfEntry newVrfEntry = new VrfEntryBuilder().setKey(new VrfEntryKey(prefix)).setDestPrefix(prefix)
1172                 .setLabel(label).setNextHopAddressList(Arrays.asList(endpointIp))
1173                 .setOrigin(RouteOrigin.INTERVPN.getValue())
1174                 .build();
1175
1176         String dstVpnRd = getVpnRd(broker, dstVpnUuid);
1177         InstanceIdentifier<VrfEntry> newVrfEntryIid =
1178                 InstanceIdentifier.builder(FibEntries.class)
1179                         .child(VrfTables.class, new VrfTablesKey(dstVpnRd))
1180                         .child(VrfEntry.class, new VrfEntryKey(newVrfEntry.getDestPrefix()))
1181                         .build();
1182         asyncWrite(broker, LogicalDatastoreType.CONFIGURATION, newVrfEntryIid, newVrfEntry);
1183
1184         // Finally, route is advertised it to the DC-GW. But while in the FibEntries the nexthop is the other
1185         // endpoint's IP, in the DC-GW the nexthop for those prefixes are the IPs of those DPNs where the target
1186         // VPN has been instantiated
1187         List<String> ecmpNexthops = new ArrayList<String>();
1188         InterVpnLinkState vpnLinkState = getInterVpnLinkState(broker, interVpnLink.getName());
1189         List<BigInteger> dpnIdList = (destinationIs1stEndpoint) ? vpnLinkState.getFirstEndpointState().getDpId()
1190                 : vpnLinkState.getSecondEndpointState().getDpId();
1191         List<String> nexthops = new ArrayList<String>();
1192         for (BigInteger dpnId : dpnIdList) {
1193             nexthops.add(InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId));
1194         }
1195         try {
1196             bgpManager.advertisePrefix(dstVpnRd, newVrfEntry.getDestPrefix(), nexthops, label.intValue());
1197         } catch (Exception exc) {
1198             LOG.error("Could not advertise prefix {} with label {} to VPN rd={}",
1199                     newVrfEntry.getDestPrefix(), label.intValue(), dstVpnRd);
1200         }
1201     }
1202
1203
1204     /**
1205      * Retrieves the ids of the currently operative DPNs
1206      *
1207      * @param dataBroker dataBroker service reference
1208      * @return the list of DPNs currently operative
1209      */
1210     public static List<BigInteger> getOperativeDPNs(DataBroker dataBroker) {
1211         List<BigInteger> result = new LinkedList<BigInteger>();
1212         InstanceIdentifier<Nodes> nodesInstanceIdentifier = InstanceIdentifier.builder(Nodes.class).build();
1213         Optional<Nodes> nodesOptional = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
1214                 nodesInstanceIdentifier);
1215         if (!nodesOptional.isPresent()) {
1216             return result;
1217         }
1218         Nodes nodes = nodesOptional.get();
1219         List<Node> nodeList = nodes.getNode();
1220         for (Node node : nodeList) {
1221             NodeId nodeId = node.getId();
1222             if (nodeId != null) {
1223                 BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeId);
1224                 result.add(dpnId);
1225             }
1226         }
1227         return result;
1228     }
1229
1230     /**
1231      * Retrieves a list of randomly selected DPNs, as many as specified.
1232      *
1233      * @param dataBroker dataBroker service reference
1234      * @param numberOfDPNs Specifies how many Operative DPNs must be found
1235      * @param excludingDPNs Specifies a blacklist of DPNs
1236      * @return the list of DPN Ids
1237      */
1238     public static List<BigInteger> pickRandomDPNs(DataBroker dataBroker, int numberOfDPNs,
1239                                                   List<BigInteger> excludingDPNs) {
1240         List<BigInteger> dpnIdPool = getOperativeDPNs(dataBroker);
1241         int poolSize = dpnIdPool.size();
1242         if (poolSize <= numberOfDPNs) {
1243             // You requested more than there is, I give you all I have.
1244             return dpnIdPool;
1245         }
1246
1247         // Random reorder
1248         Collections.shuffle(dpnIdPool);
1249         List<BigInteger> result = new ArrayList<BigInteger>();
1250
1251         for (BigInteger dpId : dpnIdPool) {
1252             if (excludingDPNs == null || !excludingDPNs.contains(dpId)) {
1253                 result.add(dpId);
1254                 if (result.size() == numberOfDPNs)
1255                     break;
1256             }
1257         }
1258
1259         if (result.size() < numberOfDPNs) {
1260             // We still don't have all we need, so we have to pick up among the "prohibited" ones
1261             dpnIdPool.removeAll(result);
1262
1263             int nbrOfProhibitedDpnsToPick = numberOfDPNs - result.size();
1264             for (int i = 0; i < nbrOfProhibitedDpnsToPick; i++) {
1265                 result.add(dpnIdPool.get(i));
1266             }
1267         }
1268         return result;
1269     }
1270
1271     public static void updateVpnInterface(DataBroker broker,String interfaceName, BigInteger dpnId, String vpnInstanceName, Boolean isScheduledToRemove){
1272         InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
1273         VpnInterface interfaceToUpdate = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(interfaceName)).setName(interfaceName)
1274                 .setDpnId(dpnId).setVpnInstanceName(vpnInstanceName).setScheduledForRemove(isScheduledToRemove).build();
1275         VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate);
1276     }
1277
1278     protected static void createVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp,
1279                                                      String portName, String macAddress, boolean isSubnetIp, boolean isConfig,
1280                                                      boolean isLearnt) {
1281         InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
1282         VpnPortipToPortBuilder builder = new VpnPortipToPortBuilder().setKey(
1283                 new VpnPortipToPortKey(fixedIp, vpnName)).setVpnName(vpnName).setPortFixedip(fixedIp).setPortName(portName)
1284                 .setMacAddress(macAddress).setSubnetIp(isSubnetIp).setConfig(isConfig).setLearnt(isLearnt);
1285         MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, builder.build());
1286         LOG.debug("ARP learned for fixedIp: {}, vpn {}, interface {}, mac {}, isSubnetIp {} added to VpnPortipToPort DS",
1287                 fixedIp, vpnName, portName, macAddress, isLearnt);
1288     }
1289
1290     protected static void updateVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp,
1291                                                      String portName, String macAddress, boolean isSubnetIp,boolean isConfig,
1292                                                      boolean isLearnt) {
1293         InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
1294         VpnPortipToPortBuilder builder = new VpnPortipToPortBuilder().setKey(
1295                 new VpnPortipToPortKey(fixedIp, vpnName)).setVpnName(vpnName).setPortFixedip(fixedIp).setPortName(portName)
1296                 .setMacAddress(macAddress).setSubnetIp(isSubnetIp).setConfig(isConfig).setLearnt(isLearnt);;
1297         MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, id, builder.build());
1298         LOG.debug("Updated Arp learnt fixedIp: {}, vpn {}, interface {}, mac {}, isLearnt {} Updated to VpnPortipToPort DS",
1299                 fixedIp, vpnName, portName, macAddress, isLearnt);
1300     }
1301
1302     protected static void removeVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp) {
1303         InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
1304         MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
1305         LOG.debug("Delete learned ARP for fixedIp: {}, vpn {} removed from VpnPortipToPort DS",
1306                 fixedIp, vpnName);
1307     }
1308
1309     static InstanceIdentifier<VpnPortipToPort> buildVpnPortipToPortIdentifier(String vpnName, String fixedIp) {
1310         InstanceIdentifier<VpnPortipToPort> id = InstanceIdentifier.builder(NeutronVpnPortipPortData.class).child
1311                 (VpnPortipToPort.class, new VpnPortipToPortKey(fixedIp, vpnName)).build();
1312         return id;
1313     }
1314
1315     static VpnPortipToPort getNeutronPortFromVpnPortFixedIp(DataBroker broker, String vpnName, String fixedIp) {
1316         InstanceIdentifier id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
1317         Optional<VpnPortipToPort> vpnPortipToPortData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
1318         if (vpnPortipToPortData.isPresent()) {
1319             return (vpnPortipToPortData.get());
1320         }
1321         return null;
1322     }
1323 }