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