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