c870d7592a4d742ef1dc4a9f7472df7aca1f24c2
[netvirt.git] / fibmanager / impl / src / main / java / org / opendaylight / netvirt / fibmanager / FibUtil.java
1 /*
2  * Copyright © 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.fibmanager;
10
11 import static java.util.stream.Collectors.joining;
12 import static java.util.stream.Collectors.toList;
13 import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
14
15 import com.google.common.base.Optional;
16 import com.google.common.base.Preconditions;
17 import com.google.common.net.InetAddresses;
18 import java.math.BigInteger;
19 import java.net.InetAddress;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.Objects;
24 import java.util.concurrent.ExecutionException;
25 import java.util.concurrent.Future;
26 import java.util.concurrent.locks.ReentrantLock;
27 import javax.annotation.Nullable;
28 import javax.inject.Inject;
29 import javax.inject.Singleton;
30 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
32 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
33 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
34 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
35 import org.opendaylight.genius.infra.Datastore.Configuration;
36 import org.opendaylight.genius.infra.Datastore.Operational;
37 import org.opendaylight.genius.infra.TypedReadTransaction;
38 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
39 import org.opendaylight.genius.infra.TypedWriteTransaction;
40 import org.opendaylight.genius.itm.api.IITMProvider;
41 import org.opendaylight.genius.mdsalutil.BucketInfo;
42 import org.opendaylight.genius.mdsalutil.MDSALUtil;
43 import org.opendaylight.genius.mdsalutil.NWUtil;
44 import org.opendaylight.genius.mdsalutil.NwConstants;
45 import org.opendaylight.genius.utils.JvmGlobalLocks;
46 import org.opendaylight.netvirt.fibmanager.NexthopManager.AdjacencyResult;
47 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
48 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
49 import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Tunnel;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockManagerService;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TimeUnits;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInputBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockOutput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInputBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockOutput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.DpidL3vpnLbNexthops;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.L3vpnLbNexthops;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpid.l3vpn.lb.nexthops.DpnLbNexthops;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpid.l3vpn.lb.nexthops.DpnLbNexthopsBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpid.l3vpn.lb.nexthops.DpnLbNexthopsKey;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.lb.nexthops.Nexthops;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.lb.nexthops.NexthopsBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.lb.nexthops.NexthopsKey;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsKey;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.vpn.extra.routes.Routes;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes.NetworkType;
120 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
121 import org.opendaylight.yangtools.yang.common.RpcResult;
122 import org.slf4j.Logger;
123 import org.slf4j.LoggerFactory;
124
125 @Singleton
126 public class FibUtil {
127     private static final Logger LOG = LoggerFactory.getLogger(FibUtil.class);
128     private static final String FLOWID_PREFIX = "L3.";
129
130     private final DataBroker dataBroker;
131     private final IdManagerService idManager;
132     private final IITMProvider iitmProvider;
133
134     @Inject
135     public FibUtil(DataBroker dataBroker, IdManagerService idManager, IITMProvider iitmProvider) {
136         this.dataBroker = dataBroker;
137         this.idManager = idManager;
138         this.iitmProvider = iitmProvider;
139     }
140
141     static InstanceIdentifier<Adjacency> getAdjacencyIdentifierOp(String vpnInterfaceName,
142                                       String vpnName, String ipAddress) {
143         LOG.debug("getAdjacencyIdentifierOp vpninterface {} vpn {} ip {}", vpnInterfaceName, vpnName, ipAddress);
144         return getAdjListPathOp(vpnInterfaceName, vpnName).builder()
145                           .child(org.opendaylight.yang.gen.v1.urn.opendaylight
146                           .netvirt.l3vpn.rev130911.adjacency.list.Adjacency.class,
147                           new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list
148                               .AdjacencyKey(ipAddress)).build();
149     }
150
151     static InstanceIdentifier<AdjacenciesOp> getAdjListPathOp(String vpnInterfaceName, String vpnName) {
152         return getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, vpnName).builder()
153             .augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
154             .AdjacenciesOp.class).build();
155     }
156
157     static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
158         return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn
159             .rev130911.PrefixToInterface.class)
160             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
161                 .VpnIds.class,
162                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
163                     .VpnIdsKey(vpnId))
164             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
165                     .vpn.ids.Prefixes.class,
166                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to
167                     ._interface.vpn.ids.PrefixesKey(ipPrefix)).build();
168     }
169
170     static InstanceIdentifier<VpnInterfaceOpDataEntry> getVpnInterfaceOpDataEntryIdentifier(
171                        String vpnInterfaceName, String vpnName) {
172         return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
173             .VpnInterfaceOpData.class)
174             .child(VpnInterfaceOpDataEntry.class,
175                 new VpnInterfaceOpDataEntryKey(vpnInterfaceName, vpnName)).build();
176     }
177
178     static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
179         return InstanceIdentifier.builder(VpnInstanceOpData.class)
180             .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
181     }
182
183     Optional<VpnInstanceOpDataEntry> getVpnInstanceOpData(String rd) {
184         InstanceIdentifier<VpnInstanceOpDataEntry> id = getVpnInstanceOpDataIdentifier(rd);
185         return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
186     }
187
188     static Optional<VpnInstanceOpDataEntry> getVpnInstanceOpData(TypedReadTransaction<Operational> operTx, String rd)
189         throws ExecutionException, InterruptedException {
190         return operTx.read(getVpnInstanceOpDataIdentifier(rd)).get();
191     }
192
193     @Nullable
194     VpnInstanceOpDataEntry getVpnInstance(String rd) {
195         InstanceIdentifier<VpnInstanceOpDataEntry> id =
196                 InstanceIdentifier.create(VpnInstanceOpData.class)
197                         .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd));
198         Optional<VpnInstanceOpDataEntry> vpnInstanceOpData =
199                 MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
200         return vpnInstanceOpData.isPresent() ? vpnInstanceOpData.get() : null;
201     }
202
203     static String getNextHopLabelKey(String rd, String prefix) {
204         return rd + FibConstants.SEPARATOR + prefix;
205     }
206
207     @Nullable
208     Prefixes getPrefixToInterface(Long vpnId, String ipPrefix) {
209         Optional<Prefixes> localNextHopInfoData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
210             getPrefixToInterfaceIdentifier(vpnId, ipPrefix));
211         return localNextHopInfoData.isPresent() ? localNextHopInfoData.get() : null;
212     }
213
214     @Nullable
215     static Prefixes getPrefixToInterface(TypedReadTransaction<Operational> operTx, Long vpnId, String ipPrefix)
216             throws ExecutionException, InterruptedException {
217         return operTx.read(getPrefixToInterfaceIdentifier(vpnId, ipPrefix)).get().orNull();
218     }
219
220     @Nullable
221     String getMacAddressFromPrefix(String ifName, String vpnName, String ipPrefix) {
222         Optional<Adjacency> adjacencyData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
223                        getAdjacencyIdentifierOp(ifName, vpnName, ipPrefix));
224         return adjacencyData.isPresent() ? adjacencyData.get().getMacAddress() : null;
225     }
226
227     void releaseId(String poolName, String idKey) {
228         ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
229         try {
230             RpcResult<ReleaseIdOutput> rpcResult = idManager.releaseId(idInput).get();
231             if (!rpcResult.isSuccessful()) {
232                 LOG.error("RPC Call to Get Unique Id for key {} returned with Errors {}", idKey, rpcResult.getErrors());
233             }
234         } catch (InterruptedException | ExecutionException e) {
235             LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
236         }
237     }
238
239     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
240         .instance.to.vpn.id.VpnInstance> getVpnInstanceToVpnIdIdentifier(String vpnName) {
241         return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
242             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
243                     .VpnInstance.class,
244                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
245                     .VpnInstanceKey(vpnName)).build();
246     }
247
248     public long getVpnId(String vpnName) {
249
250         InstanceIdentifier<VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
251         return MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
252                 VpnInstance::getVpnId).orElse(-1L);
253     }
254
255     /**
256      * Retrieves the VpnInstance name (typically the VPN Uuid) out from the route-distinguisher.
257      * @param rd The route-distinguisher
258      *
259      * @return The vpn instance
260      */
261     public Optional<String> getVpnNameFromRd(String rd) {
262         return Optional.fromJavaUtil(
263                 getVpnInstanceOpData(rd).toJavaUtil().map(VpnInstanceOpDataEntry::getVpnInstanceName));
264     }
265
266     @Nullable
267     public String getVpnNameFromId(long vpnId) {
268         InstanceIdentifier<VpnIds> id = getVpnIdToVpnInstanceIdentifier(vpnId);
269         return MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
270                 VpnIds::getVpnInstanceName).orElse(null);
271     }
272
273     static InstanceIdentifier<VpnIds> getVpnIdToVpnInstanceIdentifier(long vpnId) {
274         return InstanceIdentifier.builder(VpnIdToVpnInstance.class)
275             .child(VpnIds.class, new VpnIdsKey(vpnId)).build();
276     }
277
278     // TODO Clean up the exception handling
279     @SuppressWarnings("checkstyle:IllegalCatch")
280     public void addOrUpdateFibEntry(String rd, String macAddress, String prefix, List<String> nextHopList,
281             VrfEntry.EncapType encapType, long label, long l3vni, String gwMacAddress, String parentVpnRd,
282             RouteOrigin origin, TypedWriteTransaction<Configuration> writeConfigTxn) {
283         if (rd == null || rd.isEmpty()) {
284             LOG.error("Prefix {} not associated with vpn", prefix);
285             return;
286         }
287
288         Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
289
290         try {
291             InstanceIdentifier<VrfEntry> vrfEntryId =
292                 InstanceIdentifier.builder(FibEntries.class)
293                     .child(VrfTables.class, new VrfTablesKey(rd))
294                     .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
295
296             writeFibEntryToDs(vrfEntryId, prefix, nextHopList, label, l3vni, encapType, origin, macAddress,
297                     gwMacAddress, parentVpnRd, writeConfigTxn);
298             LOG.info("addOrUpdateFibEntry: Created/Updated vrfEntry for rd {} prefix {} nexthop {} label {} l3vni {}"
299                     + " origin {} encapType {}", rd, prefix, nextHopList, label, l3vni, origin, encapType);
300         } catch (Exception e) {
301             LOG.error("addOrUpdateFibEntry: rd {} prefix {} nexthop {} label {} l3vni {} origin {} encapType {}"
302                     + " error ", rd, prefix, nextHopList, label, l3vni, origin, encapType, e);
303         }
304     }
305
306     // TODO Clean up the exception handling
307     @SuppressWarnings("checkstyle:IllegalCatch")
308     public void writeFibEntryToDs(InstanceIdentifier<VrfEntry> vrfEntryId, String prefix, List<String> nextHopList,
309             long label, Long l3vni, VrfEntry.EncapType encapType, RouteOrigin origin, String macAddress,
310             String gatewayMacAddress, String parentVpnRd, TypedWriteTransaction<Configuration> writeConfigTxn) {
311         VrfEntryBuilder vrfEntryBuilder = new VrfEntryBuilder().setDestPrefix(prefix).setOrigin(origin.getValue());
312         if (parentVpnRd != null) {
313             vrfEntryBuilder.setParentVpnRd(parentVpnRd);
314         }
315         buildVpnEncapSpecificInfo(vrfEntryBuilder, encapType, label, l3vni, macAddress, gatewayMacAddress, nextHopList);
316         if (writeConfigTxn != null) {
317             writeConfigTxn.merge(vrfEntryId, vrfEntryBuilder.build(), CREATE_MISSING_PARENTS);
318         } else {
319             MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntryBuilder.build());
320         }
321     }
322
323     @SuppressWarnings("checkstyle:IllegalCatch")
324     public void addFibEntryForRouterInterface(String rd, String prefix, RouterInterface routerInterface, long label,
325             TypedWriteTransaction<Configuration> writeConfigTxn) {
326         if (rd == null || rd.isEmpty()) {
327             LOG.error("Prefix {} not associated with vpn", prefix);
328             return;
329         }
330
331         try {
332             InstanceIdentifier<VrfEntry> vrfEntryId =
333                 InstanceIdentifier.builder(FibEntries.class)
334                     .child(VrfTables.class, new VrfTablesKey(rd))
335                     .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
336
337             // Filling the nextHop with dummy nextHopAddress
338             VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label,
339                     FibConstants.DEFAULT_NEXTHOP_IP, RouteOrigin.LOCAL, null /* parentVpnRd */)
340                 .addAugmentation(RouterInterface.class, routerInterface).build();
341
342             if (writeConfigTxn != null) {
343                 writeConfigTxn.merge(vrfEntryId, vrfEntry, CREATE_MISSING_PARENTS);
344             } else {
345                 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
346             }
347             LOG.debug("Created vrfEntry for router-interface-prefix {} rd {} label {}", prefix, rd, label);
348         } catch (Exception e) {
349             LOG.error("addFibEntryForRouterInterface: prefix {} rd {} label {} error ", prefix, rd, label, e);
350         }
351     }
352
353     private static void buildVpnEncapSpecificInfo(VrfEntryBuilder builder, VrfEntry.EncapType encapType, long label,
354                                          long l3vni, String macAddress, String gatewayMac, List<String> nextHopList) {
355         if (encapType == null) {
356             builder.setMac(macAddress);
357             return;
358         }
359
360         // TODO - validate this check
361         if (l3vni != 0) {
362             builder.setL3vni(l3vni);
363         }
364         builder.setEncapType(encapType);
365         builder.setGatewayMacAddress(gatewayMac);
366         builder.setMac(macAddress);
367         Long lbl = encapType.equals(VrfEntry.EncapType.Mplsgre) ? label : null;
368         List<RoutePaths> routePaths = nextHopList.stream()
369                         .filter(nextHop -> nextHop != null && !nextHop.isEmpty())
370                         .map(nextHop -> FibHelper.buildRoutePath(nextHop, lbl)).collect(toList());
371         builder.setRoutePaths(routePaths);
372     }
373
374     public void removeFibEntry(String rd, String prefix, TypedWriteTransaction<Configuration> writeConfigTxn) {
375
376         if (rd == null || rd.isEmpty()) {
377             LOG.error("Prefix {} not associated with vpn", prefix);
378             return;
379         }
380         LOG.debug("removeFibEntry: Removing fib entry with destination prefix {} from vrf table for rd {}",
381                 prefix, rd);
382
383         InstanceIdentifier.InstanceIdentifierBuilder<VrfEntry> idBuilder =
384             InstanceIdentifier.builder(FibEntries.class)
385                 .child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix));
386         InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
387         if (writeConfigTxn != null) {
388             writeConfigTxn.delete(vrfEntryId);
389         } else {
390             MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
391         }
392         LOG.info("removeFibEntry: Removed Fib Entry rd {} prefix {}",rd, prefix);
393     }
394
395     /**
396      * Removes a specific Nexthop from a VrfEntry. If Nexthop to remove is the
397      * last one in the VrfEntry, then the VrfEntry is removed too.
398      * @param rd              Route-Distinguisher to which the VrfEntry belongs to
399      * @param prefix          Destination of the route
400      * @param nextHopToRemove Specific nexthop within the Route to be removed.
401      *                        If null or empty, then the whole VrfEntry is removed
402      */
403     public void removeOrUpdateFibEntry(String rd, String prefix, String nextHopToRemove,
404             TypedWriteTransaction<Configuration> writeConfigTxn) {
405
406         LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {} nextHop {}", prefix, rd,
407                 nextHopToRemove);
408
409         // Looking for existing prefix in MDSAL database
410         InstanceIdentifier<VrfEntry> vrfEntryId =
411             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
412                 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
413         Optional<VrfEntry> entry = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
414         if (entry.isPresent()) {
415             final List<RoutePaths> routePaths = entry.get().getRoutePaths();
416             if (routePaths == null || routePaths.isEmpty()) {
417                 LOG.warn("routePaths is null/empty for given rd {}, prefix {}", rd, prefix);
418                 return;
419             }
420             java.util.Optional<RoutePaths> optRoutePath =
421                     routePaths.stream()
422                         .filter(
423                             routePath -> Objects.equals(routePath.getNexthopAddress(), nextHopToRemove)).findFirst();
424             if (!optRoutePath.isPresent()) {
425                 LOG.error("Unable to find a routePath that contains the given nextHop to remove {}", nextHopToRemove);
426                 return;
427             }
428             RoutePaths routePath = optRoutePath.get();
429             if (routePaths.size() == 1) {
430                 // Remove the whole entry
431                 if (writeConfigTxn != null) {
432                     writeConfigTxn.delete(vrfEntryId);
433                 } else {
434                     MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
435                 }
436                 LOG.info("Removed Fib Entry rd {} prefix {} nextHop {}", rd, prefix, nextHopToRemove);
437             } else {
438                 InstanceIdentifier<RoutePaths> routePathsId =
439                         FibHelper.buildRoutePathId(rd, prefix, routePath.getNexthopAddress());
440                 // Remove route
441                 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, routePathsId);
442                 LOG.info("Removed Route Path rd {} prefix {}, nextHop {}, label {}", rd, prefix,
443                         routePath.getNexthopAddress(), routePath.getLabel());
444             }
445         } else {
446             LOG.warn("Could not find VrfEntry for Route-Distinguisher {} prefix {} nexthop {}", rd, prefix,
447                     nextHopToRemove);
448         }
449     }
450
451     /**
452      * Adds or removes nextHop from routePath based on the flag nextHopAdd.
453      */
454     public void updateRoutePathForFibEntry(String rd, String prefix, String nextHop, long label,
455             boolean nextHopAdd, WriteTransaction writeConfigTxn) {
456
457         LOG.debug("Updating fib entry for prefix {} with nextHop {} for rd {}.", prefix, nextHop, rd);
458
459         InstanceIdentifier<RoutePaths> routePathId = FibHelper.buildRoutePathId(rd, prefix, nextHop);
460
461         // FIXME: use routePathId instead?
462         final ReentrantLock lock = JvmGlobalLocks.getLockForString(rd + prefix + nextHop);
463         lock.lock();
464         try {
465             if (nextHopAdd) {
466                 RoutePaths routePaths = FibHelper.buildRoutePath(nextHop, label);
467                 if (writeConfigTxn != null) {
468                     writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, routePathId, routePaths,
469                             CREATE_MISSING_PARENTS);
470                 } else {
471                     MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routePathId, routePaths);
472                 }
473                 LOG.debug("Added routepath with nextHop {} for prefix {} and label {}.", nextHop, prefix, label);
474             } else {
475                 Optional<RoutePaths> routePath = MDSALUtil.read(dataBroker,
476                         LogicalDatastoreType.CONFIGURATION, routePathId);
477                 if (!routePath.isPresent()) {
478                     LOG.warn("Couldn't find RoutePath with rd {}, prefix {} and nh {} for deleting",
479                             rd, prefix, nextHop);
480                     return;
481                 }
482                 if (writeConfigTxn != null) {
483                     writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, routePathId);
484                 } else {
485                     MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, routePathId);
486                 }
487                 LOG.info("Removed routepath with nextHop {} for prefix {} and rd {}.", nextHop, prefix, rd);
488             }
489         } finally {
490             lock.unlock();
491         }
492     }
493
494     public void addVrfTable(String rd, WriteTransaction writeConfigTxn) {
495         LOG.debug("Adding vrf table for rd {}", rd);
496         InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder =
497             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
498         InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
499         VrfTablesBuilder vrfTablesBuilder = new VrfTablesBuilder().withKey(new VrfTablesKey(rd))
500             .setRouteDistinguisher(rd).setVrfEntry(new ArrayList<VrfEntry>());
501         if (writeConfigTxn != null) {
502             writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTablesBuilder.build());
503         } else {
504             MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
505                                  vrfTableId, vrfTablesBuilder.build());
506         }
507     }
508
509     public void removeVrfTable(String rd, TypedWriteTransaction<Configuration> writeConfigTxn) {
510         LOG.debug("Removing vrf table for rd {}", rd);
511         InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder =
512             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
513         InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
514
515         if (writeConfigTxn != null) {
516             writeConfigTxn.delete(vrfTableId);
517         } else {
518             Optional<VrfTables> ifStateOptional = MDSALUtil.read(dataBroker,
519                     LogicalDatastoreType.CONFIGURATION, vrfTableId);
520             if (ifStateOptional.isPresent()) {
521                 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId);
522             }
523         }
524     }
525
526     public static java.util.Optional<Long> getLabelFromRoutePaths(final VrfEntry vrfEntry) {
527         List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
528         if (routePaths == null || routePaths.isEmpty() || vrfEntry.getRoutePaths().get(0).getLabel() == null) {
529             return java.util.Optional.empty();
530         }
531         return java.util.Optional.of(vrfEntry.getRoutePaths().get(0).getLabel());
532     }
533
534     public static java.util.Optional<String> getFirstNextHopAddress(final VrfEntry vrfEntry) {
535         List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
536         if (routePaths == null || routePaths.isEmpty()) {
537             return java.util.Optional.empty();
538         }
539         return java.util.Optional.of(vrfEntry.getRoutePaths().get(0).getNexthopAddress());
540     }
541
542     public static java.util.Optional<Long> getLabelForNextHop(final VrfEntry vrfEntry, String nextHopIp) {
543         List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
544         if (routePaths == null || routePaths.isEmpty()) {
545             return java.util.Optional.empty();
546         }
547         return routePaths.stream()
548                 .filter(routePath -> Objects.equals(routePath.getNexthopAddress(), nextHopIp))
549                 .findFirst()
550                 .map(RoutePaths::getLabel);
551     }
552
553     @Nullable
554     public StateTunnelList getTunnelState(String interfaceName) throws ReadFailedException {
555         Optional<StateTunnelList> tunnelStateOptional = iitmProvider.getTunnelState(interfaceName);
556         if (tunnelStateOptional.isPresent()) {
557             return tunnelStateOptional.get();
558         }
559         return null;
560     }
561
562     public static InstanceIdentifier<Interface> buildStateInterfaceId(String interfaceName) {
563         InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
564                 InstanceIdentifier.builder(InterfacesState.class)
565                         .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
566                                 .interfaces.state.Interface.class, new org.opendaylight.yang.gen.v1.urn.ietf
567                                 .params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
568                                 .InterfaceKey(interfaceName));
569         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
570                 .interfaces.state.Interface> id = idBuilder.build();
571         return id;
572     }
573
574     @Nullable
575     public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
576         .state.Interface getInterfaceStateFromOperDS(String interfaceName) {
577         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
578             .interfaces.state.Interface> ifStateId = buildStateInterfaceId(interfaceName);
579         Optional<Interface> ifStateOptional = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, ifStateId);
580         if (ifStateOptional.isPresent()) {
581             return ifStateOptional.get();
582         }
583
584         return null;
585     }
586
587     public static String getCreateLocalNextHopJobKey(Long vpnId, BigInteger dpnId, String prefix) {
588         return "FIB-" + vpnId.toString() + "-" + dpnId.toString() + "-" + prefix;
589     }
590
591     public static String getCreateRemoteNextHopJobKey(Long vpnId, BigInteger dpnId, String prefix) {
592         return getCreateLocalNextHopJobKey(vpnId, dpnId, prefix);
593     }
594
595     public static String getJobKeyForRdPrefix(String rd, String prefix) {
596         return "FIB-" + rd + "-" + prefix;
597     }
598
599     public static String getJobKeyForVpnIdDpnId(Long vpnId, BigInteger dpnId) {
600         return "FIB-" + vpnId.toString() + "-" + dpnId.toString() ;
601     }
602
603     public void updateUsedRdAndVpnToExtraRoute(TypedReadWriteTransaction<Configuration> confTx,
604             TypedReadWriteTransaction<Operational> operTx, String tunnelIpRemoved, String primaryRd, String prefix)
605             throws ExecutionException, InterruptedException {
606         Optional<VpnInstanceOpDataEntry> optVpnInstance = getVpnInstanceOpData(operTx, primaryRd);
607         if (!optVpnInstance.isPresent()) {
608             return;
609         }
610         VpnInstanceOpDataEntry vpnInstance = optVpnInstance.get();
611         String vpnName = vpnInstance.getVpnInstanceName();
612         long vpnId = vpnInstance.getVpnId();
613         List<String> usedRds = VpnExtraRouteHelper.getUsedRds(confTx, vpnId, prefix);
614         // To identify the rd to be removed, iterate through the allocated rds for the prefix and check
615         // which rd is allocated for the particular OVS.
616         for (String usedRd : usedRds) {
617             Optional<Routes> vpnExtraRoutes = VpnExtraRouteHelper.getVpnExtraroutes(operTx, vpnName, usedRd, prefix);
618             if (vpnExtraRoutes.isPresent()) {
619                 // Since all the nexthops under one OVS will be present under one rd, only 1 nexthop is read
620                 // to identify the OVS
621                 String nextHopRemoved = vpnExtraRoutes.get().getNexthopIpList().get(0);
622                 Prefixes prefixToInterface = getPrefixToInterface(operTx, vpnId, getIpPrefix(nextHopRemoved));
623                 if (prefixToInterface != null && tunnelIpRemoved
624                         .equals(getEndpointIpAddressForDPN(prefixToInterface.getDpnId()))) {
625                     LOG.info("updating data-stores for prefix {} with primaryRd {} for interface {} on vpn {} ",
626                             prefix, primaryRd, prefixToInterface.getVpnInterfaceName(), vpnName);
627                     operTx.delete(FibUtil.getAdjacencyIdentifierOp(prefixToInterface.getVpnInterfaceName(),
628                                     vpnName, prefix));
629                     operTx.delete(VpnExtraRouteHelper.getVpnToExtrarouteVrfIdIdentifier(vpnName, usedRd, prefix));
630                     confTx.delete(VpnExtraRouteHelper.getUsedRdsIdentifier(vpnId, prefix, nextHopRemoved));
631                     break;
632                 }
633             }
634         }
635     }
636
637     private String getEndpointIpAddressForDPN(BigInteger dpnId) {
638         //TODO: Move it to a common place for vpn and fib
639         String nextHopIp = null;
640         InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
641             InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpnId)).build();
642         Optional<DPNTEPsInfo> tunnelInfo = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, tunnelInfoId);
643         if (tunnelInfo.isPresent()) {
644             List<TunnelEndPoints> nexthopIpList = tunnelInfo.get().getTunnelEndPoints();
645             if (nexthopIpList != null && !nexthopIpList.isEmpty()) {
646                 nextHopIp = nexthopIpList.get(0).getIpAddress().stringValue();
647             }
648         }
649         return nextHopIp;
650     }
651
652     public static String getIpPrefix(String prefix) {
653         String[] prefixValues = prefix.split(FibConstants.PREFIX_SEPARATOR);
654         if (prefixValues.length == 1) {
655             return NWUtil.toIpPrefix(prefix);
656         }
657         return prefix;
658     }
659
660     public static boolean isTunnelInterface(AdjacencyResult adjacencyResult) {
661         return Tunnel.class.equals(adjacencyResult.getInterfaceType());
662     }
663
664     public static InstanceIdentifier<VrfEntry> getNextHopIdentifier(String rd, String prefix) {
665         return InstanceIdentifier.builder(FibEntries.class)
666                 .child(VrfTables.class,new VrfTablesKey(rd)).child(VrfEntry.class,new VrfEntryKey(prefix)).build();
667     }
668
669     public List<String> getNextHopAddresses(String rd, String prefix) {
670         InstanceIdentifier<VrfEntry> vrfEntryId = getNextHopIdentifier(rd, prefix);
671         Optional<VrfEntry> vrfEntry = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
672         if (vrfEntry.isPresent()) {
673             return FibHelper.getNextHopListFromRoutePaths(vrfEntry.get());
674         } else {
675             return Collections.emptyList();
676         }
677     }
678
679     public static String getGreLbGroupKey(List<String> availableDcGws) {
680         Preconditions.checkNotNull(availableDcGws, "AvailableDcGws is null");
681         return "gre-" + availableDcGws.stream().sorted().collect(joining(":"));
682     }
683
684     public static void updateLbGroupInfo(BigInteger dpnId, String destinationIp, String groupIdKey,
685             String groupId, TypedWriteTransaction<Operational> tx) {
686         InstanceIdentifier<DpnLbNexthops> id = getDpnLbNexthopsIdentifier(dpnId, destinationIp);
687         DpnLbNexthops dpnToLbNextHop = buildDpnLbNextHops(dpnId, destinationIp, groupIdKey);
688         tx.merge(id, dpnToLbNextHop);
689         InstanceIdentifier<Nexthops> nextHopsId = getNextHopsIdentifier(groupIdKey);
690         Nexthops nextHopsToGroupId = buildNextHops(dpnId, groupIdKey, groupId);
691         tx.merge(nextHopsId, nextHopsToGroupId);
692     }
693
694     public static void removeDpnIdToNextHopInfo(String destinationIp, BigInteger dpnId,
695             TypedWriteTransaction<Operational> tx) {
696         tx.delete(getDpnLbNexthopsIdentifier(dpnId, destinationIp));
697     }
698
699     public static void removeOrUpdateNextHopInfo(BigInteger dpnId, String nextHopKey, String groupId,
700             Nexthops nexthops, TypedWriteTransaction<Operational> tx) {
701         InstanceIdentifier<Nexthops> nextHopsId = getNextHopsIdentifier(nextHopKey);
702         List<String> targetDeviceIds =
703             nexthops.getTargetDeviceId() != null ? new ArrayList<>(nexthops.getTargetDeviceId()) : new ArrayList<>();
704         targetDeviceIds.remove(dpnId.toString());
705         if (targetDeviceIds.isEmpty()) {
706             tx.delete(nextHopsId);
707         } else {
708             Nexthops nextHopsToGroupId = new NexthopsBuilder().withKey(new NexthopsKey(nextHopKey))
709                 .setNexthopKey(nextHopKey)
710                 .setGroupId(groupId)
711                 .setTargetDeviceId(targetDeviceIds).build();
712             tx.put(nextHopsId, nextHopsToGroupId);
713         }
714     }
715
716     private static InstanceIdentifier<DpnLbNexthops> getDpnLbNexthopsIdentifier(BigInteger dpnId,
717             String destinationIp) {
718         return InstanceIdentifier.builder(DpidL3vpnLbNexthops.class)
719                 .child(DpnLbNexthops.class, new DpnLbNexthopsKey(destinationIp, dpnId))
720                 .build();
721     }
722
723     private static InstanceIdentifier<Nexthops> getNextHopsIdentifier(String groupIdKey) {
724         return InstanceIdentifier.builder(L3vpnLbNexthops.class)
725                 .child(Nexthops.class, new NexthopsKey(groupIdKey)).build();
726     }
727
728     private static Nexthops buildNextHops(BigInteger dpnId, String groupIdKey, String groupId) {
729         return new NexthopsBuilder().withKey(new NexthopsKey(groupIdKey))
730                 .setNexthopKey(groupIdKey)
731                 .setGroupId(groupId)
732                 .setTargetDeviceId(Collections.singletonList(dpnId.toString())).build();
733     }
734
735     private static DpnLbNexthops buildDpnLbNextHops(BigInteger dpnId, String destinationIp,
736             String groupIdKey) {
737         return new DpnLbNexthopsBuilder().withKey(new DpnLbNexthopsKey(destinationIp, dpnId))
738                 .setDstDeviceId(destinationIp).setSrcDpId(dpnId)
739                 .setNexthopKey(Collections.singletonList(groupIdKey)).build();
740     }
741
742     public Optional<Nexthops> getNexthops(String nextHopKey) {
743         InstanceIdentifier<Nexthops> nextHopsId = InstanceIdentifier.builder(L3vpnLbNexthops.class)
744                 .child(Nexthops.class, new NexthopsKey(nextHopKey)).build();
745         return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, nextHopsId);
746     }
747
748     public Optional<DpnLbNexthops> getDpnLbNexthops(BigInteger dpnId, String destinationIp) {
749         InstanceIdentifier<DpnLbNexthops> id = InstanceIdentifier.builder(DpidL3vpnLbNexthops.class)
750                 .child(DpnLbNexthops.class, new DpnLbNexthopsKey(destinationIp, dpnId))
751                 .build();
752         return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
753     }
754
755     static boolean isVxlanNetwork(NetworkType networkType) {
756         if (networkType != null) {
757             return networkType == NetworkAttributes.NetworkType.VXLAN;
758         }
759         return false;
760     }
761
762     static boolean isBgpVpn(String vpnName, String rd) {
763         return vpnName != null && !vpnName.equals(rd);
764     }
765
766     static NodeRef buildNodeRef(BigInteger dpId) {
767         return new NodeRef(InstanceIdentifier.builder(Nodes.class)
768                 .child(Node.class, new NodeKey(new NodeId("openflow:" + dpId))).build());
769     }
770
771     static InstanceIdentifier<Group> buildGroupInstanceIdentifier(long groupId, BigInteger dpId) {
772         return InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(new NodeId("openflow:" + dpId)))
773                 .augmentation(FlowCapableNode.class).child(Group.class, new GroupKey(new GroupId(groupId))).build();
774     }
775
776     static Buckets buildBuckets(List<BucketInfo> listBucketInfo) {
777         long index = 0;
778         BucketsBuilder bucketsBuilder = new BucketsBuilder();
779         if (listBucketInfo != null) {
780             List<Bucket> bucketList = new ArrayList<>();
781
782             for (BucketInfo bucketInfo : listBucketInfo) {
783                 BucketBuilder bucketBuilder = new BucketBuilder();
784                 bucketBuilder.setAction(bucketInfo.buildActions());
785                 bucketBuilder.setWeight(bucketInfo.getWeight());
786                 bucketBuilder.setBucketId(new BucketId(index++));
787                 bucketBuilder.setWeight(bucketInfo.getWeight()).setWatchPort(bucketInfo.getWatchPort())
788                         .setWatchGroup(bucketInfo.getWatchGroup());
789                 bucketList.add(bucketBuilder.build());
790             }
791
792             bucketsBuilder.setBucket(bucketList);
793         }
794         return bucketsBuilder.build();
795     }
796
797     static String getFlowRef(BigInteger dpnId, short tableId, long label, int priority) {
798         return FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId + NwConstants.FLOWID_SEPARATOR + label
799                 + NwConstants.FLOWID_SEPARATOR + priority;
800     }
801
802     static String getFlowRef(BigInteger dpnId, short tableId, String rd, int priority, InetAddress destPrefix) {
803         return FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId + NwConstants.FLOWID_SEPARATOR + rd
804                 + NwConstants.FLOWID_SEPARATOR + priority + NwConstants.FLOWID_SEPARATOR + destPrefix.getHostAddress();
805     }
806
807     static String getL3VpnGatewayFlowRef(short l3GwMacTable, BigInteger dpId, long vpnId, String gwMacAddress) {
808         return gwMacAddress + NwConstants.FLOWID_SEPARATOR + vpnId + NwConstants.FLOWID_SEPARATOR + dpId
809                 + NwConstants.FLOWID_SEPARATOR + l3GwMacTable;
810     }
811
812     static Node buildDpnNode(BigInteger dpnId) {
813         return new NodeBuilder().setId(new NodeId("openflow:" + dpnId))
814                 .withKey(new NodeKey(new NodeId("openflow:" + dpnId))).build();
815     }
816
817     public static String getBroadcastAddressFromCidr(String cidr) {
818         String[] ipaddressValues = cidr.split("/");
819         int address = InetAddresses.coerceToInteger(InetAddresses.forString(ipaddressValues[0]));
820         int cidrPart = Integer.parseInt(ipaddressValues[1]);
821         int netmask = 0;
822         for (int j = 0; j < cidrPart; ++j) {
823             netmask |= 1 << 31 - j;
824         }
825         int network = address & netmask;
826         int broadcast = network | ~netmask;
827         return InetAddresses.toAddrString(InetAddresses.fromInteger(broadcast));
828     }
829
830     public static boolean lockCluster(LockManagerService lockManager, String lockName, long tryLockPeriod) {
831         TryLockInput input = new TryLockInputBuilder().setLockName(lockName).setTime(tryLockPeriod)
832                 .setTimeUnit(TimeUnits.Milliseconds).build();
833         Future<RpcResult<TryLockOutput>> result = lockManager.tryLock(input);
834         boolean lockAcquired;
835         try {
836             if (result != null && result.get().isSuccessful()) {
837                 LOG.debug("lockCluster: Acquired lock for {}", lockName);
838                 lockAcquired = true;
839             } else {
840                 LOG.error("lockCluster: Unable to getLock for {}", lockName);
841                 lockAcquired = false;
842             }
843         } catch (InterruptedException | ExecutionException e) {
844             LOG.error("lockCluster: Exception while trying to getLock for {}", lockName, e);
845             lockAcquired = false;
846         }
847
848         return lockAcquired;
849     }
850
851     public static void unlockCluster(LockManagerService lockManager, String lockName) {
852         UnlockInput input = new UnlockInputBuilder().setLockName(lockName).build();
853         Future<RpcResult<UnlockOutput>> result = lockManager.unlock(input);
854         try {
855             if (result != null && result.get().isSuccessful()) {
856                 LOG.debug("unlockCluster: Unlocked {}", lockName);
857             } else {
858                 LOG.error("unlockCluster: Unable to release lock for {}", lockName);
859             }
860         } catch (InterruptedException | ExecutionException e) {
861             LOG.error("unlockCluster: Unable to unlock {}", lockName, e);
862         }
863     }
864
865     public boolean isInterfacePresentInDpn(String vpnName, BigInteger dpnId) {
866         InstanceIdentifier<VpnToDpnList> vpnToDpnListId = InstanceIdentifier.builder(VpnInstanceOpData.class)
867                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vpnName))
868                 .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
869         try {
870             VpnToDpnList vpnToDpnList = SingleTransactionDataBroker.syncRead(dataBroker,
871                     LogicalDatastoreType.OPERATIONAL, vpnToDpnListId);
872             if (!(vpnToDpnList == null) && !(vpnToDpnList.getVpnInterfaces() == null)
873                     && !vpnToDpnList.getVpnInterfaces().isEmpty()) {
874                 return true;
875             }
876         } catch (ReadFailedException e) {
877             LOG.warn("Failed to read interfaces with error {}", e.getMessage());
878         }
879         return false;
880     }
881 }