2 * Copyright © 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
9 package org.opendaylight.netvirt.fibmanager;
11 import static java.util.stream.Collectors.joining;
12 import static java.util.stream.Collectors.toList;
13 import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
15 import com.google.common.base.Optional;
16 import com.google.common.base.Preconditions;
17 import com.google.common.net.InetAddresses;
18 import java.net.InetAddress;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.Objects;
23 import java.util.concurrent.ExecutionException;
24 import java.util.concurrent.Future;
25 import java.util.concurrent.locks.ReentrantLock;
26 import javax.inject.Inject;
27 import javax.inject.Singleton;
28 import org.eclipse.jdt.annotation.Nullable;
29 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
30 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
31 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
32 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
33 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
34 import org.opendaylight.genius.infra.Datastore.Configuration;
35 import org.opendaylight.genius.infra.Datastore.Operational;
36 import org.opendaylight.genius.infra.TypedReadTransaction;
37 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
38 import org.opendaylight.genius.infra.TypedWriteTransaction;
39 import org.opendaylight.genius.itm.api.IITMProvider;
40 import org.opendaylight.genius.mdsalutil.BucketInfo;
41 import org.opendaylight.genius.mdsalutil.MDSALUtil;
42 import org.opendaylight.genius.mdsalutil.NWUtil;
43 import org.opendaylight.genius.mdsalutil.NwConstants;
44 import org.opendaylight.genius.utils.JvmGlobalLocks;
45 import org.opendaylight.netvirt.fibmanager.NexthopManager.AdjacencyResult;
46 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
47 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
48 import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Tunnel;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockManagerService;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TimeUnits;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInputBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockOutput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInputBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockOutput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.L3vpnDcGws;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.L3vpnLbNexthops;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.dc.gws.DcGateway;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.dc.gws.DcGatewayBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.dc.gws.DcGatewayKey;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.lb.nexthops.Nexthops;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.lb.nexthops.NexthopsBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.lb.nexthops.NexthopsKey;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsKey;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.vpn.extra.routes.Routes;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes.NetworkType;
119 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
120 import org.opendaylight.yangtools.yang.common.RpcResult;
121 import org.opendaylight.yangtools.yang.common.Uint32;
122 import org.opendaylight.yangtools.yang.common.Uint64;
123 import org.slf4j.Logger;
124 import org.slf4j.LoggerFactory;
127 public class FibUtil {
128 private static final Logger LOG = LoggerFactory.getLogger(FibUtil.class);
129 private static final String FLOWID_PREFIX = "L3.";
131 private final DataBroker dataBroker;
132 private final IdManagerService idManager;
133 private final IITMProvider iitmProvider;
136 public FibUtil(DataBroker dataBroker, IdManagerService idManager, IITMProvider iitmProvider) {
137 this.dataBroker = dataBroker;
138 this.idManager = idManager;
139 this.iitmProvider = iitmProvider;
142 static InstanceIdentifier<Adjacency> getAdjacencyIdentifierOp(String vpnInterfaceName,
143 String vpnName, String ipAddress) {
144 LOG.debug("getAdjacencyIdentifierOp vpninterface {} vpn {} ip {}", vpnInterfaceName, vpnName, ipAddress);
145 return getAdjListPathOp(vpnInterfaceName, vpnName).builder()
146 .child(org.opendaylight.yang.gen.v1.urn.opendaylight
147 .netvirt.l3vpn.rev130911.adjacency.list.Adjacency.class,
148 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list
149 .AdjacencyKey(ipAddress)).build();
152 static InstanceIdentifier<AdjacenciesOp> getAdjListPathOp(String vpnInterfaceName, String vpnName) {
153 return getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, vpnName).builder()
154 .augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
155 .AdjacenciesOp.class).build();
158 static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(Uint32 vpnId, String ipPrefix) {
159 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn
160 .rev130911.PrefixToInterface.class)
161 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
163 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
165 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
166 .vpn.ids.Prefixes.class,
167 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to
168 ._interface.vpn.ids.PrefixesKey(ipPrefix)).build();
171 static InstanceIdentifier<VpnInterfaceOpDataEntry> getVpnInterfaceOpDataEntryIdentifier(
172 String vpnInterfaceName, String vpnName) {
173 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
174 .VpnInterfaceOpData.class)
175 .child(VpnInterfaceOpDataEntry.class,
176 new VpnInterfaceOpDataEntryKey(vpnInterfaceName, vpnName)).build();
179 static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
180 return InstanceIdentifier.builder(VpnInstanceOpData.class)
181 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
184 Optional<VpnInstanceOpDataEntry> getVpnInstanceOpData(String rd) {
185 InstanceIdentifier<VpnInstanceOpDataEntry> id = getVpnInstanceOpDataIdentifier(rd);
186 return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
189 static Optional<VpnInstanceOpDataEntry> getVpnInstanceOpData(TypedReadTransaction<Operational> operTx, String rd)
190 throws ExecutionException, InterruptedException {
191 return operTx.read(getVpnInstanceOpDataIdentifier(rd)).get();
195 VpnInstanceOpDataEntry getVpnInstance(String rd) {
196 InstanceIdentifier<VpnInstanceOpDataEntry> id =
197 InstanceIdentifier.create(VpnInstanceOpData.class)
198 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd));
199 Optional<VpnInstanceOpDataEntry> vpnInstanceOpData =
200 MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
201 return vpnInstanceOpData.isPresent() ? vpnInstanceOpData.get() : null;
204 static String getNextHopLabelKey(String rd, String prefix) {
205 return rd + FibConstants.SEPARATOR + prefix;
209 Prefixes getPrefixToInterface(Uint32 vpnId, String ipPrefix) {
210 Optional<Prefixes> localNextHopInfoData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
211 getPrefixToInterfaceIdentifier(vpnId, ipPrefix));
212 return localNextHopInfoData.isPresent() ? localNextHopInfoData.get() : null;
216 static Prefixes getPrefixToInterface(TypedReadTransaction<Operational> operTx, Uint32 vpnId, String ipPrefix)
217 throws ExecutionException, InterruptedException {
218 return operTx.read(getPrefixToInterfaceIdentifier(vpnId, ipPrefix)).get().orNull();
222 String getMacAddressFromPrefix(String ifName, String vpnName, String ipPrefix) {
223 Optional<Adjacency> adjacencyData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
224 getAdjacencyIdentifierOp(ifName, vpnName, ipPrefix));
225 return adjacencyData.isPresent() ? adjacencyData.get().getMacAddress() : null;
228 void releaseId(String poolName, String idKey) {
229 ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
231 RpcResult<ReleaseIdOutput> rpcResult = idManager.releaseId(idInput).get();
232 if (!rpcResult.isSuccessful()) {
233 LOG.error("RPC Call to Get Unique Id for key {} returned with Errors {}", idKey, rpcResult.getErrors());
235 } catch (InterruptedException | ExecutionException e) {
236 LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
240 static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
241 .instance.to.vpn.id.VpnInstance> getVpnInstanceToVpnIdIdentifier(String vpnName) {
242 return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
243 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
245 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
246 .VpnInstanceKey(vpnName)).build();
249 public Uint32 getVpnId(String vpnName) {
251 InstanceIdentifier<VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
252 return MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
253 VpnInstance::getVpnId).orElse(Uint32.ZERO);
257 * Retrieves the VpnInstance name (typically the VPN Uuid) out from the route-distinguisher.
258 * @param rd The route-distinguisher
260 * @return The vpn instance
262 public Optional<String> getVpnNameFromRd(String rd) {
263 return Optional.fromJavaUtil(
264 getVpnInstanceOpData(rd).toJavaUtil().map(VpnInstanceOpDataEntry::getVpnInstanceName));
268 public String getVpnNameFromId(Uint32 vpnId) {
269 InstanceIdentifier<VpnIds> id = getVpnIdToVpnInstanceIdentifier(vpnId);
270 return MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
271 VpnIds::getVpnInstanceName).orElse(null);
274 static InstanceIdentifier<VpnIds> getVpnIdToVpnInstanceIdentifier(Uint32 vpnId) {
275 return InstanceIdentifier.builder(VpnIdToVpnInstance.class)
276 .child(VpnIds.class, new VpnIdsKey(vpnId)).build();
279 // TODO Clean up the exception handling
280 @SuppressWarnings("checkstyle:IllegalCatch")
281 public void addOrUpdateFibEntry(String rd, String macAddress, String prefix, List<String> nextHopList,
282 VrfEntry.EncapType encapType, Uint32 label, Uint32 l3vni, String gwMacAddress, String parentVpnRd,
283 RouteOrigin origin, TypedWriteTransaction<Configuration> writeConfigTxn) {
284 if (rd == null || rd.isEmpty()) {
285 LOG.error("Prefix {} not associated with vpn", prefix);
289 Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
292 InstanceIdentifier<VrfEntry> vrfEntryId =
293 InstanceIdentifier.builder(FibEntries.class)
294 .child(VrfTables.class, new VrfTablesKey(rd))
295 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
297 writeFibEntryToDs(vrfEntryId, prefix, nextHopList, label, l3vni, encapType, origin, macAddress,
298 gwMacAddress, parentVpnRd, writeConfigTxn);
299 LOG.info("addOrUpdateFibEntry: Created/Updated vrfEntry for rd {} prefix {} nexthop {} label {} l3vni {}"
300 + " origin {} encapType {}", rd, prefix, nextHopList, label, l3vni, origin, encapType);
301 } catch (Exception e) {
302 LOG.error("addOrUpdateFibEntry: rd {} prefix {} nexthop {} label {} l3vni {} origin {} encapType {}"
303 + " error ", rd, prefix, nextHopList, label, l3vni, origin, encapType, e);
307 // TODO Clean up the exception handling
308 @SuppressWarnings("checkstyle:IllegalCatch")
309 public void writeFibEntryToDs(InstanceIdentifier<VrfEntry> vrfEntryId, String prefix, List<String> nextHopList,
310 Uint32 label, Uint32 l3vni, VrfEntry.EncapType encapType, RouteOrigin origin, String macAddress,
311 String gatewayMacAddress, String parentVpnRd, TypedWriteTransaction<Configuration> writeConfigTxn) {
312 VrfEntryBuilder vrfEntryBuilder = new VrfEntryBuilder().setDestPrefix(prefix).setOrigin(origin.getValue());
313 if (parentVpnRd != null) {
314 vrfEntryBuilder.setParentVpnRd(parentVpnRd);
316 buildVpnEncapSpecificInfo(vrfEntryBuilder, encapType, label, l3vni, macAddress, gatewayMacAddress, nextHopList);
317 if (writeConfigTxn != null) {
318 writeConfigTxn.merge(vrfEntryId, vrfEntryBuilder.build(), CREATE_MISSING_PARENTS);
320 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntryBuilder.build());
324 @SuppressWarnings("checkstyle:IllegalCatch")
325 public void addFibEntryForRouterInterface(String rd, String prefix, RouterInterface routerInterface, Uint32 label,
326 TypedWriteTransaction<Configuration> writeConfigTxn) {
327 if (rd == null || rd.isEmpty()) {
328 LOG.error("Prefix {} not associated with vpn", prefix);
333 InstanceIdentifier<VrfEntry> vrfEntryId =
334 InstanceIdentifier.builder(FibEntries.class)
335 .child(VrfTables.class, new VrfTablesKey(rd))
336 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
338 // Filling the nextHop with dummy nextHopAddress
339 VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label,
340 FibConstants.DEFAULT_NEXTHOP_IP, RouteOrigin.LOCAL, null /* parentVpnRd */)
341 .addAugmentation(RouterInterface.class, routerInterface).build();
343 if (writeConfigTxn != null) {
344 writeConfigTxn.merge(vrfEntryId, vrfEntry, CREATE_MISSING_PARENTS);
346 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
348 LOG.debug("Created vrfEntry for router-interface-prefix {} rd {} label {}", prefix, rd, label);
349 } catch (Exception e) {
350 LOG.error("addFibEntryForRouterInterface: prefix {} rd {} label {} error ", prefix, rd, label, e);
354 private static void buildVpnEncapSpecificInfo(VrfEntryBuilder builder, VrfEntry.EncapType encapType, Uint32 label,
355 Uint32 l3vni, String macAddress, String gatewayMac, List<String> nextHopList) {
356 if (encapType == null) {
357 builder.setMac(macAddress);
361 // TODO - validate this check
362 if (l3vni.longValue() != 0) {
363 builder.setL3vni(l3vni);
365 builder.setEncapType(encapType);
366 builder.setGatewayMacAddress(gatewayMac);
367 builder.setMac(macAddress);
368 Uint32 lbl = encapType.equals(VrfEntry.EncapType.Mplsgre) ? label : null;
369 List<RoutePaths> routePaths = nextHopList.stream()
370 .filter(nextHop -> nextHop != null && !nextHop.isEmpty())
371 .map(nextHop -> FibHelper.buildRoutePath(nextHop, lbl)).collect(toList());
372 builder.setRoutePaths(routePaths);
375 public void removeFibEntry(String rd, String prefix, TypedWriteTransaction<Configuration> writeConfigTxn) {
377 if (rd == null || rd.isEmpty()) {
378 LOG.error("Prefix {} not associated with vpn", prefix);
381 LOG.debug("removeFibEntry: Removing fib entry with destination prefix {} from vrf table for rd {}",
384 InstanceIdentifier.InstanceIdentifierBuilder<VrfEntry> idBuilder =
385 InstanceIdentifier.builder(FibEntries.class)
386 .child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix));
387 InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
388 if (writeConfigTxn != null) {
389 writeConfigTxn.delete(vrfEntryId);
391 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
393 LOG.info("removeFibEntry: Removed Fib Entry rd {} prefix {}",rd, prefix);
397 * Removes a specific Nexthop from a VrfEntry. If Nexthop to remove is the
398 * last one in the VrfEntry, then the VrfEntry is removed too.
399 * @param rd Route-Distinguisher to which the VrfEntry belongs to
400 * @param prefix Destination of the route
401 * @param nextHopToRemove Specific nexthop within the Route to be removed.
402 * If null or empty, then the whole VrfEntry is removed
404 public void removeOrUpdateFibEntry(String rd, String prefix, String nextHopToRemove,
405 TypedWriteTransaction<Configuration> writeConfigTxn) {
407 LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {} nextHop {}", prefix, rd,
410 // Looking for existing prefix in MDSAL database
411 InstanceIdentifier<VrfEntry> vrfEntryId =
412 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
413 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
414 Optional<VrfEntry> entry = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
415 if (entry.isPresent()) {
416 final List<RoutePaths> routePaths = entry.get().getRoutePaths();
417 if (routePaths == null || routePaths.isEmpty()) {
418 LOG.warn("routePaths is null/empty for given rd {}, prefix {}", rd, prefix);
421 java.util.Optional<RoutePaths> optRoutePath =
424 routePath -> Objects.equals(routePath.getNexthopAddress(), nextHopToRemove)).findFirst();
425 if (!optRoutePath.isPresent()) {
426 LOG.error("Unable to find a routePath that contains the given nextHop to remove {}", nextHopToRemove);
429 RoutePaths routePath = optRoutePath.get();
430 if (routePaths.size() == 1) {
431 // Remove the whole entry
432 if (writeConfigTxn != null) {
433 writeConfigTxn.delete(vrfEntryId);
435 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
437 LOG.info("Removed Fib Entry rd {} prefix {} nextHop {}", rd, prefix, nextHopToRemove);
439 InstanceIdentifier<RoutePaths> routePathsId =
440 FibHelper.buildRoutePathId(rd, prefix, routePath.getNexthopAddress());
442 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, routePathsId);
443 LOG.info("Removed Route Path rd {} prefix {}, nextHop {}, label {}", rd, prefix,
444 routePath.getNexthopAddress(), routePath.getLabel());
447 LOG.warn("Could not find VrfEntry for Route-Distinguisher {} prefix {} nexthop {}", rd, prefix,
453 * Adds or removes nextHop from routePath based on the flag nextHopAdd.
455 public void updateRoutePathForFibEntry(String rd, String prefix, String nextHop, Uint32 label,
456 boolean nextHopAdd, WriteTransaction writeConfigTxn) {
458 LOG.debug("Updating fib entry for prefix {} with nextHop {} for rd {}.", prefix, nextHop, rd);
460 InstanceIdentifier<RoutePaths> routePathId = FibHelper.buildRoutePathId(rd, prefix, nextHop);
462 // FIXME: use routePathId instead?
463 final ReentrantLock lock = JvmGlobalLocks.getLockForString(rd + prefix + nextHop);
467 RoutePaths routePaths = FibHelper.buildRoutePath(nextHop, label);
468 if (writeConfigTxn != null) {
469 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, routePathId, routePaths,
470 CREATE_MISSING_PARENTS);
472 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routePathId, routePaths);
474 LOG.debug("Added routepath with nextHop {} for prefix {} and label {}.", nextHop, prefix, label);
476 Optional<RoutePaths> routePath = MDSALUtil.read(dataBroker,
477 LogicalDatastoreType.CONFIGURATION, routePathId);
478 if (!routePath.isPresent()) {
479 LOG.warn("Couldn't find RoutePath with rd {}, prefix {} and nh {} for deleting",
480 rd, prefix, nextHop);
483 if (writeConfigTxn != null) {
484 writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, routePathId);
486 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, routePathId);
488 LOG.info("Removed routepath with nextHop {} for prefix {} and rd {}.", nextHop, prefix, rd);
495 public void addVrfTable(String rd, WriteTransaction writeConfigTxn) {
496 LOG.debug("Adding vrf table for rd {}", rd);
497 InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder =
498 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
499 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
500 VrfTablesBuilder vrfTablesBuilder = new VrfTablesBuilder().withKey(new VrfTablesKey(rd))
501 .setRouteDistinguisher(rd).setVrfEntry(new ArrayList<VrfEntry>());
502 if (writeConfigTxn != null) {
503 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTablesBuilder.build());
505 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
506 vrfTableId, vrfTablesBuilder.build());
510 public void removeVrfTable(String rd, TypedWriteTransaction<Configuration> writeConfigTxn) {
511 LOG.debug("Removing vrf table for rd {}", rd);
512 InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder =
513 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
514 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
516 if (writeConfigTxn != null) {
517 writeConfigTxn.delete(vrfTableId);
519 Optional<VrfTables> ifStateOptional = MDSALUtil.read(dataBroker,
520 LogicalDatastoreType.CONFIGURATION, vrfTableId);
521 if (ifStateOptional.isPresent()) {
522 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId);
527 public static java.util.Optional<Uint32> getLabelFromRoutePaths(final VrfEntry vrfEntry) {
528 List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
529 if (routePaths == null || routePaths.isEmpty() || vrfEntry.getRoutePaths().get(0).getLabel() == null) {
530 return java.util.Optional.empty();
532 return java.util.Optional.of(vrfEntry.getRoutePaths().get(0).getLabel());
535 public static java.util.Optional<String> getFirstNextHopAddress(final VrfEntry vrfEntry) {
536 List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
537 if (routePaths == null || routePaths.isEmpty()) {
538 return java.util.Optional.empty();
540 return java.util.Optional.of(vrfEntry.getRoutePaths().get(0).getNexthopAddress());
543 public static java.util.Optional<Uint32> getLabelForNextHop(final VrfEntry vrfEntry, String nextHopIp) {
544 List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
545 if (routePaths == null || routePaths.isEmpty()) {
546 return java.util.Optional.empty();
548 return routePaths.stream()
549 .filter(routePath -> Objects.equals(routePath.getNexthopAddress(), nextHopIp))
551 .map(RoutePaths::getLabel);
555 public StateTunnelList getTunnelState(String interfaceName) throws ReadFailedException {
556 Optional<StateTunnelList> tunnelStateOptional = iitmProvider.getTunnelState(interfaceName);
557 if (tunnelStateOptional.isPresent()) {
558 return tunnelStateOptional.get();
563 public static InstanceIdentifier<Interface> buildStateInterfaceId(String interfaceName) {
564 InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
565 InstanceIdentifier.builder(InterfacesState.class)
566 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
567 .interfaces.state.Interface.class, new org.opendaylight.yang.gen.v1.urn.ietf
568 .params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
569 .InterfaceKey(interfaceName));
570 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
571 .interfaces.state.Interface> id = idBuilder.build();
575 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
576 .@Nullable Interface getInterfaceStateFromOperDS(String interfaceName) {
577 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
578 .interfaces.state.Interface> ifStateId = buildStateInterfaceId(interfaceName);
579 Optional<Interface> ifStateOptional = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, ifStateId);
580 if (ifStateOptional.isPresent()) {
581 return ifStateOptional.get();
587 public static String getCreateLocalNextHopJobKey(Uint32 vpnId, Uint64 dpnId, String prefix) {
588 return "FIB-" + vpnId.toString() + "-" + dpnId.toString() + "-" + prefix;
591 public static String getCreateRemoteNextHopJobKey(Uint32 vpnId, Uint64 dpnId, String prefix) {
592 return getCreateLocalNextHopJobKey(vpnId, dpnId, prefix);
595 public static String getJobKeyForRdPrefix(String rd, String prefix) {
596 return "FIB-" + rd + "-" + prefix;
599 public static String getJobKeyForVpnIdDpnId(Uint32 vpnId, Uint64 dpnId) {
600 return "FIB-" + vpnId.toString() + "-" + dpnId.toString() ;
603 public void updateUsedRdAndVpnToExtraRoute(TypedReadWriteTransaction<Configuration> confTx,
604 TypedReadWriteTransaction<Operational> operTx, String tunnelIpRemoved, String primaryRd, String prefix)
605 throws ExecutionException, InterruptedException {
606 Optional<VpnInstanceOpDataEntry> optVpnInstance = getVpnInstanceOpData(operTx, primaryRd);
607 if (!optVpnInstance.isPresent()) {
610 VpnInstanceOpDataEntry vpnInstance = optVpnInstance.get();
611 String vpnName = vpnInstance.getVpnInstanceName();
612 Uint32 vpnId = vpnInstance.getVpnId();
613 List<String> usedRds = VpnExtraRouteHelper.getUsedRds(confTx, vpnId, prefix);
614 // To identify the rd to be removed, iterate through the allocated rds for the prefix and check
615 // which rd is allocated for the particular OVS.
616 for (String usedRd : usedRds) {
617 Optional<Routes> vpnExtraRoutes = VpnExtraRouteHelper.getVpnExtraroutes(operTx, vpnName, usedRd, prefix);
618 if (vpnExtraRoutes.isPresent()) {
619 // Since all the nexthops under one OVS will be present under one rd, only 1 nexthop is read
620 // to identify the OVS
621 String nextHopRemoved = vpnExtraRoutes.get().getNexthopIpList().get(0);
622 Prefixes prefixToInterface = getPrefixToInterface(operTx, vpnId, getIpPrefix(nextHopRemoved));
623 if (prefixToInterface != null && tunnelIpRemoved
624 .equals(getEndpointIpAddressForDPN(prefixToInterface.getDpnId()))) {
625 LOG.info("updating data-stores for prefix {} with primaryRd {} for interface {} on vpn {} ",
626 prefix, primaryRd, prefixToInterface.getVpnInterfaceName(), vpnName);
627 operTx.delete(FibUtil.getAdjacencyIdentifierOp(prefixToInterface.getVpnInterfaceName(),
629 operTx.delete(VpnExtraRouteHelper.getVpnToExtrarouteVrfIdIdentifier(vpnName, usedRd, prefix));
630 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
631 VpnExtraRouteHelper.getUsedRdsIdentifier(vpnId, prefix, nextHopRemoved));
638 private String getEndpointIpAddressForDPN(Uint64 dpnId) {
639 //TODO: Move it to a common place for vpn and fib
640 String nextHopIp = null;
641 InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
642 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpnId)).build();
643 Optional<DPNTEPsInfo> tunnelInfo = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, tunnelInfoId);
644 if (tunnelInfo.isPresent()) {
645 List<TunnelEndPoints> nexthopIpList = tunnelInfo.get().getTunnelEndPoints();
646 if (nexthopIpList != null && !nexthopIpList.isEmpty()) {
647 nextHopIp = nexthopIpList.get(0).getIpAddress().stringValue();
653 public static String getIpPrefix(String prefix) {
654 String[] prefixValues = prefix.split(FibConstants.PREFIX_SEPARATOR);
655 if (prefixValues.length == 1) {
656 return NWUtil.toIpPrefix(prefix);
661 public static boolean isTunnelInterface(AdjacencyResult adjacencyResult) {
662 return Tunnel.class.equals(adjacencyResult.getInterfaceType());
665 public static InstanceIdentifier<VrfEntry> getNextHopIdentifier(String rd, String prefix) {
666 return InstanceIdentifier.builder(FibEntries.class)
667 .child(VrfTables.class,new VrfTablesKey(rd)).child(VrfEntry.class,new VrfEntryKey(prefix)).build();
670 public List<String> getNextHopAddresses(String rd, String prefix) {
671 InstanceIdentifier<VrfEntry> vrfEntryId = getNextHopIdentifier(rd, prefix);
672 Optional<VrfEntry> vrfEntry = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
673 if (vrfEntry.isPresent()) {
674 return FibHelper.getNextHopListFromRoutePaths(vrfEntry.get());
676 return Collections.emptyList();
680 public static String getGreLbGroupKey(List<String> availableDcGws) {
681 Preconditions.checkNotNull(availableDcGws, "AvailableDcGws is null");
682 return "gre-" + availableDcGws.stream().sorted().collect(joining(":"));
685 public static void updateLbGroupInfo(Uint64 dpnId, String groupIdKey,
686 String groupId, TypedWriteTransaction<Operational> tx) {
687 InstanceIdentifier<Nexthops> nextHopsId = getNextHopsIdentifier(groupIdKey);
688 Nexthops nextHopsToGroupId = buildNextHops(dpnId, groupIdKey, groupId);
689 tx.merge(nextHopsId, nextHopsToGroupId);
692 public static void removeL3vpnDcGateWay(String destinationIp, TypedReadWriteTransaction<Operational> tx)
693 throws InterruptedException, ExecutionException {
694 InstanceIdentifier<DcGateway> dcGateWayId = getDcGwInstance(destinationIp);
695 Optional<DcGateway> dcGateWayOpt = tx.read(dcGateWayId).get();
696 if (!dcGateWayOpt.isPresent()) {
699 tx.delete(dcGateWayId);
702 public static void addL3vpnDcGateWay(String destinationIp, TypedReadWriteTransaction<Operational> tx)
703 throws InterruptedException, ExecutionException {
704 InstanceIdentifier<DcGateway> dcGateWayId = getDcGwInstance(destinationIp);
705 Optional<DcGateway> dcGateWayOpt = tx.read(dcGateWayId).get();
706 if (!dcGateWayOpt.isPresent()) {
708 new DcGatewayBuilder()
709 .withKey(new DcGatewayKey(destinationIp))
710 .setIpAddress(destinationIp).build()
715 private static InstanceIdentifier<DcGateway> getDcGwInstance(String destinationIp) {
716 return InstanceIdentifier.builder(L3vpnDcGws.class)
717 .child(DcGateway.class, new DcGatewayKey(destinationIp))
721 public static void removeOrUpdateNextHopInfo(Uint64 dpnId, String nextHopKey, String groupId,
722 Nexthops nexthops, TypedWriteTransaction<Operational> tx) {
723 InstanceIdentifier<Nexthops> nextHopsId = getNextHopsIdentifier(nextHopKey);
724 List<String> targetDeviceIds =
725 nexthops.getTargetDeviceId() != null ? new ArrayList<>(nexthops.getTargetDeviceId()) : new ArrayList<>();
726 targetDeviceIds.remove(dpnId.toString());
727 if (targetDeviceIds.isEmpty()) {
728 tx.delete(nextHopsId);
730 Nexthops nextHopsToGroupId = new NexthopsBuilder().withKey(new NexthopsKey(nextHopKey))
731 .setNexthopKey(nextHopKey)
733 .setTargetDeviceId(targetDeviceIds).build();
734 tx.put(nextHopsId, nextHopsToGroupId);
738 private static InstanceIdentifier<Nexthops> getNextHopsIdentifier(String groupIdKey) {
739 return InstanceIdentifier.builder(L3vpnLbNexthops.class)
740 .child(Nexthops.class, new NexthopsKey(groupIdKey)).build();
743 private static Nexthops buildNextHops(Uint64 dpnId, String groupIdKey, String groupId) {
744 return new NexthopsBuilder().withKey(new NexthopsKey(groupIdKey))
745 .setNexthopKey(groupIdKey)
747 .setTargetDeviceId(Collections.singletonList(dpnId.toString())).build();
750 public Optional<Nexthops> getNexthops(String nextHopKey) {
751 InstanceIdentifier<Nexthops> nextHopsId = InstanceIdentifier.builder(L3vpnLbNexthops.class)
752 .child(Nexthops.class, new NexthopsKey(nextHopKey)).build();
753 return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, nextHopsId);
756 public List<String> getL3VpnDcGateWays() {
757 InstanceIdentifier<L3vpnDcGws> id = InstanceIdentifier.builder(L3vpnDcGws.class)
759 Optional<L3vpnDcGws> dcGwsOpt = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
760 if (!dcGwsOpt.isPresent()) {
761 return Collections.emptyList();
763 return dcGwsOpt.get().getDcGateway().stream().map(DcGateway::getIpAddress).collect(toList());
766 static boolean isVxlanNetwork(NetworkType networkType) {
767 if (networkType != null) {
768 return networkType == NetworkAttributes.NetworkType.VXLAN;
773 static boolean isBgpVpn(String vpnName, String rd) {
774 return vpnName != null && !vpnName.equals(rd);
777 static NodeRef buildNodeRef(Uint64 dpId) {
778 return new NodeRef(InstanceIdentifier.builder(Nodes.class)
779 .child(Node.class, new NodeKey(new NodeId("openflow:" + dpId))).build());
782 static InstanceIdentifier<Group> buildGroupInstanceIdentifier(long groupId, Uint64 dpId) {
783 return InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(new NodeId("openflow:" + dpId)))
784 .augmentation(FlowCapableNode.class).child(Group.class, new GroupKey(new GroupId(groupId))).build();
787 static Buckets buildBuckets(List<BucketInfo> listBucketInfo) {
789 BucketsBuilder bucketsBuilder = new BucketsBuilder();
790 if (listBucketInfo != null) {
791 List<Bucket> bucketList = new ArrayList<>();
793 for (BucketInfo bucketInfo : listBucketInfo) {
794 BucketBuilder bucketBuilder = new BucketBuilder();
795 bucketBuilder.setAction(bucketInfo.buildActions());
796 bucketBuilder.setWeight(bucketInfo.getWeight());
797 bucketBuilder.setBucketId(new BucketId(index++));
798 bucketBuilder.setWeight(bucketInfo.getWeight()).setWatchPort(bucketInfo.getWatchPort())
799 .setWatchGroup(bucketInfo.getWatchGroup());
800 bucketList.add(bucketBuilder.build());
803 bucketsBuilder.setBucket(bucketList);
805 return bucketsBuilder.build();
808 static String getFlowRef(Uint64 dpnId, short tableId, Uint32 label, int priority) {
809 return FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId + NwConstants.FLOWID_SEPARATOR + label
810 + NwConstants.FLOWID_SEPARATOR + priority;
813 static String getFlowRef(Uint64 dpnId, short tableId, String rd, int priority, InetAddress destPrefix) {
814 return FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId + NwConstants.FLOWID_SEPARATOR + rd
815 + NwConstants.FLOWID_SEPARATOR + priority + NwConstants.FLOWID_SEPARATOR + destPrefix.getHostAddress();
818 static String getL3VpnGatewayFlowRef(short l3GwMacTable, Uint64 dpId, Uint32 vpnId, String gwMacAddress) {
819 return gwMacAddress + NwConstants.FLOWID_SEPARATOR + vpnId + NwConstants.FLOWID_SEPARATOR + dpId
820 + NwConstants.FLOWID_SEPARATOR + l3GwMacTable;
823 static Node buildDpnNode(Uint64 dpnId) {
824 return new NodeBuilder().setId(new NodeId("openflow:" + dpnId))
825 .withKey(new NodeKey(new NodeId("openflow:" + dpnId))).build();
828 public static String getBroadcastAddressFromCidr(String cidr) {
829 String[] ipaddressValues = cidr.split("/");
830 int address = InetAddresses.coerceToInteger(InetAddresses.forString(ipaddressValues[0]));
831 int cidrPart = Integer.parseInt(ipaddressValues[1]);
833 for (int j = 0; j < cidrPart; ++j) {
834 netmask |= 1 << 31 - j;
836 int network = address & netmask;
837 int broadcast = network | ~netmask;
838 return InetAddresses.toAddrString(InetAddresses.fromInteger(broadcast));
841 public static boolean lockCluster(LockManagerService lockManager, String lockName, long tryLockPeriod) {
842 TryLockInput input = new TryLockInputBuilder().setLockName(lockName).setTime(tryLockPeriod)
843 .setTimeUnit(TimeUnits.Milliseconds).build();
844 Future<RpcResult<TryLockOutput>> result = lockManager.tryLock(input);
845 boolean lockAcquired;
847 if (result != null && result.get().isSuccessful()) {
848 LOG.debug("lockCluster: Acquired lock for {}", lockName);
851 LOG.error("lockCluster: Unable to getLock for {}", lockName);
852 lockAcquired = false;
854 } catch (InterruptedException | ExecutionException e) {
855 LOG.error("lockCluster: Exception while trying to getLock for {}", lockName, e);
856 lockAcquired = false;
862 public static void unlockCluster(LockManagerService lockManager, String lockName) {
863 UnlockInput input = new UnlockInputBuilder().setLockName(lockName).build();
864 Future<RpcResult<UnlockOutput>> result = lockManager.unlock(input);
866 if (result != null && result.get().isSuccessful()) {
867 LOG.debug("unlockCluster: Unlocked {}", lockName);
869 LOG.error("unlockCluster: Unable to release lock for {}", lockName);
871 } catch (InterruptedException | ExecutionException e) {
872 LOG.error("unlockCluster: Unable to unlock {}", lockName, e);
876 public boolean isInterfacePresentInDpn(String vpnName, Uint64 dpnId) {
877 InstanceIdentifier<VpnToDpnList> vpnToDpnListId = InstanceIdentifier.builder(VpnInstanceOpData.class)
878 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vpnName))
879 .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
881 VpnToDpnList vpnToDpnList = SingleTransactionDataBroker.syncRead(dataBroker,
882 LogicalDatastoreType.OPERATIONAL, vpnToDpnListId);
883 if (!(vpnToDpnList == null) && !(vpnToDpnList.getVpnInterfaces() == null)
884 && !vpnToDpnList.getVpnInterfaces().isEmpty()) {
887 } catch (ReadFailedException e) {
888 LOG.warn("Failed to read interfaces with error {}", e.getMessage());