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.Collections.emptyList;
12 import static java.util.stream.Collectors.joining;
13 import static java.util.stream.Collectors.toList;
14 import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
16 import com.google.common.base.Optional;
17 import com.google.common.base.Preconditions;
18 import com.google.common.net.InetAddresses;
19 import java.math.BigInteger;
20 import java.net.InetAddress;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.List;
24 import java.util.Objects;
25 import java.util.concurrent.ExecutionException;
26 import java.util.concurrent.Future;
27 import javax.annotation.Nonnull;
28 import javax.annotation.Nullable;
29 import javax.inject.Inject;
30 import javax.inject.Singleton;
31 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
32 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
33 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
34 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
35 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
36 import org.opendaylight.genius.infra.Datastore.Configuration;
37 import org.opendaylight.genius.infra.Datastore.Operational;
38 import org.opendaylight.genius.infra.TypedReadTransaction;
39 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
40 import org.opendaylight.genius.infra.TypedWriteTransaction;
41 import org.opendaylight.genius.itm.api.IITMProvider;
42 import org.opendaylight.genius.mdsalutil.BucketInfo;
43 import org.opendaylight.genius.mdsalutil.MDSALUtil;
44 import org.opendaylight.genius.mdsalutil.NWUtil;
45 import org.opendaylight.genius.mdsalutil.NwConstants;
46 import org.opendaylight.netvirt.elanmanager.api.IElanService;
47 import org.opendaylight.netvirt.fibmanager.NexthopManager.AdjacencyResult;
48 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
49 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
50 import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.Tunnel;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnEndpoints;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockManagerService;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TimeUnits;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInputBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockOutput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInputBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockOutput;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.DpidL3vpnLbNexthops;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.L3vpnLbNexthops;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpid.l3vpn.lb.nexthops.DpnLbNexthops;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpid.l3vpn.lb.nexthops.DpnLbNexthopsBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.dpid.l3vpn.lb.nexthops.DpnLbNexthopsKey;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.lb.nexthops.Nexthops;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.lb.nexthops.NexthopsBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.l3vpn.lb.nexthops.NexthopsKey;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsKey;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.vpn.extra.routes.Routes;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes.NetworkType;
122 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
123 import org.opendaylight.yangtools.yang.common.RpcResult;
124 import org.slf4j.Logger;
125 import org.slf4j.LoggerFactory;
128 public class FibUtil {
129 private static final Logger LOG = LoggerFactory.getLogger(FibUtil.class);
130 private static final String FLOWID_PREFIX = "L3.";
132 private final DataBroker dataBroker;
133 private final IElanService elanManager;
134 private final IdManagerService idManager;
135 private final IITMProvider iitmProvider;
138 public FibUtil(DataBroker dataBroker, IElanService elanManager, IdManagerService idManager,
139 IITMProvider iitmProvider) {
140 this.dataBroker = dataBroker;
141 this.elanManager = elanManager;
142 this.idManager = idManager;
143 this.iitmProvider = iitmProvider;
146 static InstanceIdentifier<Adjacency> getAdjacencyIdentifier(String vpnInterfaceName, String ipAddress) {
147 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang
148 .l3vpn.rev140815.VpnInterfaces.class)
149 .child(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces
151 new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces
152 .VpnInterfaceKey(vpnInterfaceName))
153 .augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies.class)
154 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.class,
155 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list
156 .AdjacencyKey(ipAddress)).build();
159 static InstanceIdentifier<Adjacency> getAdjacencyIdentifierOp(String vpnInterfaceName,
160 String vpnName, String ipAddress) {
161 LOG.debug("getAdjacencyIdentifierOp vpninterface {} vpn {} ip {}", vpnInterfaceName, vpnName, ipAddress);
162 return getAdjListPathOp(vpnInterfaceName, vpnName).builder()
163 .child(org.opendaylight.yang.gen.v1.urn.opendaylight
164 .netvirt.l3vpn.rev130911.adjacency.list.Adjacency.class,
165 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list
166 .AdjacencyKey(ipAddress)).build();
169 static InstanceIdentifier<Adjacencies> getAdjListPath(String vpnInterfaceName) {
170 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn
171 .rev140815.VpnInterfaces.class)
172 .child(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces
174 new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces
175 .VpnInterfaceKey(vpnInterfaceName))
176 .augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies.class)
180 static InstanceIdentifier<AdjacenciesOp> getAdjListPathOp(String vpnInterfaceName, String vpnName) {
181 return getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName, vpnName).builder()
182 .augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
183 .AdjacenciesOp.class).build();
186 static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
187 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn
188 .rev130911.PrefixToInterface.class)
189 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
191 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
193 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
194 .vpn.ids.Prefixes.class,
195 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to
196 ._interface.vpn.ids.PrefixesKey(ipPrefix)).build();
199 static InstanceIdentifier<VpnInterfaceOpDataEntry> getVpnInterfaceOpDataEntryIdentifier(
200 String vpnInterfaceName, String vpnName) {
201 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
202 .VpnInterfaceOpData.class)
203 .child(VpnInterfaceOpDataEntry.class,
204 new VpnInterfaceOpDataEntryKey(vpnInterfaceName, vpnName)).build();
207 static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
208 return InstanceIdentifier.builder(VpnInstanceOpData.class)
209 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
212 Optional<VpnInstanceOpDataEntry> getVpnInstanceOpData(String rd) {
213 InstanceIdentifier<VpnInstanceOpDataEntry> id = getVpnInstanceOpDataIdentifier(rd);
214 return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
217 static Optional<VpnInstanceOpDataEntry> getVpnInstanceOpData(TypedReadTransaction<Operational> operTx, String rd)
218 throws ExecutionException, InterruptedException {
219 return operTx.read(getVpnInstanceOpDataIdentifier(rd)).get();
223 VpnInstanceOpDataEntry getVpnInstance(String rd) {
224 InstanceIdentifier<VpnInstanceOpDataEntry> id =
225 InstanceIdentifier.create(VpnInstanceOpData.class)
226 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd));
227 Optional<VpnInstanceOpDataEntry> vpnInstanceOpData =
228 MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
229 return vpnInstanceOpData.isPresent() ? vpnInstanceOpData.get() : null;
232 static String getNextHopLabelKey(String rd, String prefix) {
233 return rd + FibConstants.SEPARATOR + prefix;
237 Prefixes getPrefixToInterface(Long vpnId, String ipPrefix) {
238 Optional<Prefixes> localNextHopInfoData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
239 getPrefixToInterfaceIdentifier(vpnId, ipPrefix));
240 return localNextHopInfoData.isPresent() ? localNextHopInfoData.get() : null;
244 static Prefixes getPrefixToInterface(TypedReadTransaction<Operational> operTx, Long vpnId, String ipPrefix)
245 throws ExecutionException, InterruptedException {
246 return operTx.read(getPrefixToInterfaceIdentifier(vpnId, ipPrefix)).get().orNull();
250 String getMacAddressFromPrefix(String ifName, String vpnName, String ipPrefix) {
251 Optional<Adjacency> adjacencyData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
252 getAdjacencyIdentifierOp(ifName, vpnName, ipPrefix));
253 return adjacencyData.isPresent() ? adjacencyData.get().getMacAddress() : null;
256 void releaseId(String poolName, String idKey) {
257 ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
259 RpcResult<ReleaseIdOutput> rpcResult = idManager.releaseId(idInput).get();
260 if (!rpcResult.isSuccessful()) {
261 LOG.error("RPC Call to Get Unique Id for key {} returned with Errors {}", idKey, rpcResult.getErrors());
263 } catch (InterruptedException | ExecutionException e) {
264 LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
268 static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
269 .instance.to.vpn.id.VpnInstance> getVpnInstanceToVpnIdIdentifier(String vpnName) {
270 return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
271 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
273 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
274 .VpnInstanceKey(vpnName)).build();
277 public long getVpnId(String vpnName) {
279 InstanceIdentifier<VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
280 return MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
281 VpnInstance::getVpnId).orElse(-1L);
285 * Retrieves the VpnInstance name (typically the VPN Uuid) out from the route-distinguisher.
286 * @param rd The route-distinguisher
288 * @return The vpn instance
290 public Optional<String> getVpnNameFromRd(String rd) {
291 return Optional.fromJavaUtil(
292 getVpnInstanceOpData(rd).toJavaUtil().map(VpnInstanceOpDataEntry::getVpnInstanceName));
296 public String getVpnNameFromId(long vpnId) {
297 InstanceIdentifier<VpnIds> id = getVpnIdToVpnInstanceIdentifier(vpnId);
298 return MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
299 VpnIds::getVpnInstanceName).orElse(null);
302 static InstanceIdentifier<VpnIds> getVpnIdToVpnInstanceIdentifier(long vpnId) {
303 return InstanceIdentifier.builder(VpnIdToVpnInstance.class)
304 .child(VpnIds.class, new VpnIdsKey(vpnId)).build();
307 // TODO Clean up the exception handling
308 @SuppressWarnings("checkstyle:IllegalCatch")
309 public void addOrUpdateFibEntry(String rd, String macAddress, String prefix, List<String> nextHopList,
310 VrfEntry.EncapType encapType, long label, long l3vni, String gwMacAddress, String parentVpnRd,
311 RouteOrigin origin, TypedWriteTransaction<Configuration> writeConfigTxn) {
312 if (rd == null || rd.isEmpty()) {
313 LOG.error("Prefix {} not associated with vpn", prefix);
317 Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
320 InstanceIdentifier<VrfEntry> vrfEntryId =
321 InstanceIdentifier.builder(FibEntries.class)
322 .child(VrfTables.class, new VrfTablesKey(rd))
323 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
325 writeFibEntryToDs(vrfEntryId, prefix, nextHopList, label, l3vni, encapType, origin, macAddress,
326 gwMacAddress, parentVpnRd, writeConfigTxn);
327 LOG.info("addOrUpdateFibEntry: Created/Updated vrfEntry for rd {} prefix {} nexthop {} label {} l3vni {}"
328 + " origin {} encapType {}", rd, prefix, nextHopList, label, l3vni, origin, encapType);
329 } catch (Exception e) {
330 LOG.error("addOrUpdateFibEntry: rd {} prefix {} nexthop {} label {} l3vni {} origin {} encapType {}"
331 + " error ", rd, prefix, nextHopList, label, l3vni, origin, encapType, e);
335 // TODO Clean up the exception handling
336 @SuppressWarnings("checkstyle:IllegalCatch")
337 public void writeFibEntryToDs(InstanceIdentifier<VrfEntry> vrfEntryId, String prefix, List<String> nextHopList,
338 long label, Long l3vni, VrfEntry.EncapType encapType, RouteOrigin origin, String macAddress,
339 String gatewayMacAddress, String parentVpnRd, TypedWriteTransaction<Configuration> writeConfigTxn) {
340 VrfEntryBuilder vrfEntryBuilder = new VrfEntryBuilder().setDestPrefix(prefix).setOrigin(origin.getValue());
341 if (parentVpnRd != null) {
342 vrfEntryBuilder.setParentVpnRd(parentVpnRd);
344 buildVpnEncapSpecificInfo(vrfEntryBuilder, encapType, label, l3vni, macAddress, gatewayMacAddress, nextHopList);
345 if (writeConfigTxn != null) {
346 writeConfigTxn.merge(vrfEntryId, vrfEntryBuilder.build(), CREATE_MISSING_PARENTS);
348 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntryBuilder.build());
352 @SuppressWarnings("checkstyle:IllegalCatch")
353 public void addFibEntryForRouterInterface(String rd, String prefix, RouterInterface routerInterface, long label,
354 TypedWriteTransaction<Configuration> writeConfigTxn) {
355 if (rd == null || rd.isEmpty()) {
356 LOG.error("Prefix {} not associated with vpn", prefix);
361 InstanceIdentifier<VrfEntry> vrfEntryId =
362 InstanceIdentifier.builder(FibEntries.class)
363 .child(VrfTables.class, new VrfTablesKey(rd))
364 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
366 // Filling the nextHop with dummy nextHopAddress
367 VrfEntry vrfEntry = FibHelper.getVrfEntryBuilder(prefix, label,
368 FibConstants.DEFAULT_NEXTHOP_IP, RouteOrigin.LOCAL, null /* parentVpnRd */)
369 .addAugmentation(RouterInterface.class, routerInterface).build();
371 if (writeConfigTxn != null) {
372 writeConfigTxn.merge(vrfEntryId, vrfEntry, CREATE_MISSING_PARENTS);
374 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
376 LOG.debug("Created vrfEntry for router-interface-prefix {} rd {} label {}", prefix, rd, label);
377 } catch (Exception e) {
378 LOG.error("addFibEntryForRouterInterface: prefix {} rd {} label {} error ", prefix, rd, label, e);
382 private static void buildVpnEncapSpecificInfo(VrfEntryBuilder builder, VrfEntry.EncapType encapType, long label,
383 long l3vni, String macAddress, String gatewayMac, List<String> nextHopList) {
384 if (encapType == null) {
385 builder.setMac(macAddress);
389 // TODO - validate this check
391 builder.setL3vni(l3vni);
393 builder.setEncapType(encapType);
394 builder.setGatewayMacAddress(gatewayMac);
395 builder.setMac(macAddress);
396 Long lbl = encapType.equals(VrfEntry.EncapType.Mplsgre) ? label : null;
397 List<RoutePaths> routePaths = nextHopList.stream()
398 .filter(nextHop -> nextHop != null && !nextHop.isEmpty())
399 .map(nextHop -> FibHelper.buildRoutePath(nextHop, lbl)).collect(toList());
400 builder.setRoutePaths(routePaths);
403 public void removeFibEntry(String rd, String prefix, TypedWriteTransaction<Configuration> writeConfigTxn) {
405 if (rd == null || rd.isEmpty()) {
406 LOG.error("Prefix {} not associated with vpn", prefix);
409 LOG.debug("removeFibEntry: Removing fib entry with destination prefix {} from vrf table for rd {}",
412 InstanceIdentifier.InstanceIdentifierBuilder<VrfEntry> idBuilder =
413 InstanceIdentifier.builder(FibEntries.class)
414 .child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix));
415 InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
416 if (writeConfigTxn != null) {
417 writeConfigTxn.delete(vrfEntryId);
419 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
421 LOG.info("removeFibEntry: Removed Fib Entry rd {} prefix {}",rd, prefix);
425 * Removes a specific Nexthop from a VrfEntry. If Nexthop to remove is the
426 * last one in the VrfEntry, then the VrfEntry is removed too.
427 * @param rd Route-Distinguisher to which the VrfEntry belongs to
428 * @param prefix Destination of the route
429 * @param nextHopToRemove Specific nexthop within the Route to be removed.
430 * If null or empty, then the whole VrfEntry is removed
432 public void removeOrUpdateFibEntry(String rd, String prefix, String nextHopToRemove,
433 TypedWriteTransaction<Configuration> writeConfigTxn) {
435 LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {} nextHop {}", prefix, rd,
438 // Looking for existing prefix in MDSAL database
439 InstanceIdentifier<VrfEntry> vrfEntryId =
440 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
441 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
442 Optional<VrfEntry> entry = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
443 if (entry.isPresent()) {
444 final List<RoutePaths> routePaths = entry.get().getRoutePaths();
445 if (routePaths == null || routePaths.isEmpty()) {
446 LOG.warn("routePaths is null/empty for given rd {}, prefix {}", rd, prefix);
449 java.util.Optional<RoutePaths> optRoutePath =
452 routePath -> Objects.equals(routePath.getNexthopAddress(), nextHopToRemove)).findFirst();
453 if (!optRoutePath.isPresent()) {
454 LOG.error("Unable to find a routePath that contains the given nextHop to remove {}", nextHopToRemove);
457 RoutePaths routePath = optRoutePath.get();
458 if (routePaths.size() == 1) {
459 // Remove the whole entry
460 if (writeConfigTxn != null) {
461 writeConfigTxn.delete(vrfEntryId);
463 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
465 LOG.info("Removed Fib Entry rd {} prefix {} nextHop {}", rd, prefix, nextHopToRemove);
467 InstanceIdentifier<RoutePaths> routePathsId =
468 FibHelper.buildRoutePathId(rd, prefix, routePath.getNexthopAddress());
470 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, routePathsId);
471 LOG.info("Removed Route Path rd {} prefix {}, nextHop {}, label {}", rd, prefix,
472 routePath.getNexthopAddress(), routePath.getLabel());
475 LOG.warn("Could not find VrfEntry for Route-Distinguisher {} prefix {} nexthop {}", rd, prefix,
481 * Adds or removes nextHop from routePath based on the flag nextHopAdd.
483 public void updateRoutePathForFibEntry(String rd, String prefix, String nextHop, long label,
484 boolean nextHopAdd, WriteTransaction writeConfigTxn) {
486 LOG.debug("Updating fib entry for prefix {} with nextHop {} for rd {}.", prefix, nextHop, rd);
488 InstanceIdentifier<RoutePaths> routePathId = FibHelper.buildRoutePathId(rd, prefix, nextHop);
489 String routePathKey = rd + prefix + nextHop;
490 synchronized (routePathKey.intern()) {
492 RoutePaths routePaths = FibHelper.buildRoutePath(nextHop, label);
493 if (writeConfigTxn != null) {
494 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, routePathId, routePaths,
495 CREATE_MISSING_PARENTS);
497 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routePathId, routePaths);
499 LOG.debug("Added routepath with nextHop {} for prefix {} and label {}.", nextHop, prefix, label);
501 Optional<RoutePaths> routePath = MDSALUtil.read(dataBroker,
502 LogicalDatastoreType.CONFIGURATION, routePathId);
503 if (!routePath.isPresent()) {
504 LOG.warn("Couldn't find RoutePath with rd {}, prefix {} and nh {} for deleting",
505 rd, prefix, nextHop);
508 if (writeConfigTxn != null) {
509 writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, routePathId);
511 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, routePathId);
513 LOG.info("Removed routepath with nextHop {} for prefix {} and rd {}.", nextHop, prefix, rd);
518 public void addVrfTable(String rd, WriteTransaction writeConfigTxn) {
519 LOG.debug("Adding vrf table for rd {}", rd);
520 InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder =
521 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
522 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
523 VrfTablesBuilder vrfTablesBuilder = new VrfTablesBuilder().withKey(new VrfTablesKey(rd))
524 .setRouteDistinguisher(rd).setVrfEntry(new ArrayList<VrfEntry>());
525 if (writeConfigTxn != null) {
526 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTablesBuilder.build());
528 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
529 vrfTableId, vrfTablesBuilder.build());
533 public void removeVrfTable(String rd, TypedWriteTransaction<Configuration> writeConfigTxn) {
534 LOG.debug("Removing vrf table for rd {}", rd);
535 InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder =
536 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
537 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
539 if (writeConfigTxn != null) {
540 writeConfigTxn.delete(vrfTableId);
542 Optional<VrfTables> ifStateOptional = MDSALUtil.read(dataBroker,
543 LogicalDatastoreType.CONFIGURATION, vrfTableId);
544 if (ifStateOptional.isPresent()) {
545 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId);
550 public static java.util.Optional<Long> getLabelFromRoutePaths(final VrfEntry vrfEntry) {
551 List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
552 if (routePaths == null || routePaths.isEmpty() || vrfEntry.getRoutePaths().get(0).getLabel() == null) {
553 return java.util.Optional.empty();
555 return java.util.Optional.of(vrfEntry.getRoutePaths().get(0).getLabel());
558 public static java.util.Optional<String> getFirstNextHopAddress(final VrfEntry vrfEntry) {
559 List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
560 if (routePaths == null || routePaths.isEmpty()) {
561 return java.util.Optional.empty();
563 return java.util.Optional.of(vrfEntry.getRoutePaths().get(0).getNexthopAddress());
566 public static java.util.Optional<Long> getLabelForNextHop(final VrfEntry vrfEntry, String nextHopIp) {
567 List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
568 if (routePaths == null || routePaths.isEmpty()) {
569 return java.util.Optional.empty();
571 return routePaths.stream()
572 .filter(routePath -> Objects.equals(routePath.getNexthopAddress(), nextHopIp))
574 .map(RoutePaths::getLabel);
578 public StateTunnelList getTunnelState(String interfaceName) throws ReadFailedException {
579 Optional<StateTunnelList> tunnelStateOptional = iitmProvider.getTunnelState(interfaceName);
580 if (tunnelStateOptional.isPresent()) {
581 return tunnelStateOptional.get();
586 public static InstanceIdentifier<Interface> buildStateInterfaceId(String interfaceName) {
587 InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
588 InstanceIdentifier.builder(InterfacesState.class)
589 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
590 .interfaces.state.Interface.class, new org.opendaylight.yang.gen.v1.urn.ietf
591 .params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
592 .InterfaceKey(interfaceName));
593 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
594 .interfaces.state.Interface> id = idBuilder.build();
599 public org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
600 .state.Interface getInterfaceStateFromOperDS(String interfaceName) {
601 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
602 .interfaces.state.Interface> ifStateId = buildStateInterfaceId(interfaceName);
603 Optional<Interface> ifStateOptional = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, ifStateId);
604 if (ifStateOptional.isPresent()) {
605 return ifStateOptional.get();
611 public static String getCreateLocalNextHopJobKey(Long vpnId, BigInteger dpnId, String prefix) {
612 return "FIB-" + vpnId.toString() + "-" + dpnId.toString() + "-" + prefix;
615 public static String getCreateRemoteNextHopJobKey(Long vpnId, BigInteger dpnId, String prefix) {
616 return getCreateLocalNextHopJobKey(vpnId, dpnId, prefix);
619 public static String getJobKeyForRdPrefix(String rd, String prefix) {
620 return "FIB-" + rd + "-" + prefix;
623 public static String getJobKeyForVpnIdDpnId(Long vpnId, BigInteger dpnId) {
624 return "FIB-" + vpnId.toString() + "-" + dpnId.toString() ;
627 public void updateUsedRdAndVpnToExtraRoute(TypedReadWriteTransaction<Configuration> confTx,
628 TypedReadWriteTransaction<Operational> operTx, String tunnelIpRemoved, String primaryRd, String prefix)
629 throws ExecutionException, InterruptedException {
630 Optional<VpnInstanceOpDataEntry> optVpnInstance = getVpnInstanceOpData(operTx, primaryRd);
631 if (!optVpnInstance.isPresent()) {
634 VpnInstanceOpDataEntry vpnInstance = optVpnInstance.get();
635 String vpnName = vpnInstance.getVpnInstanceName();
636 long vpnId = vpnInstance.getVpnId();
637 List<String> usedRds = VpnExtraRouteHelper.getUsedRds(confTx, vpnId, prefix);
638 // To identify the rd to be removed, iterate through the allocated rds for the prefix and check
639 // which rd is allocated for the particular OVS.
640 for (String usedRd : usedRds) {
641 Optional<Routes> vpnExtraRoutes = VpnExtraRouteHelper.getVpnExtraroutes(operTx, vpnName, usedRd, prefix);
642 if (vpnExtraRoutes.isPresent()) {
643 // Since all the nexthops under one OVS will be present under one rd, only 1 nexthop is read
644 // to identify the OVS
645 String nextHopRemoved = vpnExtraRoutes.get().getNexthopIpList().get(0);
646 Prefixes prefixToInterface = getPrefixToInterface(operTx, vpnId, getIpPrefix(nextHopRemoved));
647 if (prefixToInterface != null && tunnelIpRemoved
648 .equals(getEndpointIpAddressForDPN(prefixToInterface.getDpnId()))) {
649 LOG.info("updating data-stores for prefix {} with primaryRd {} for interface {} on vpn {} ",
650 prefix, primaryRd, prefixToInterface.getVpnInterfaceName(), vpnName);
651 operTx.delete(FibUtil.getAdjacencyIdentifierOp(prefixToInterface.getVpnInterfaceName(),
653 operTx.delete(VpnExtraRouteHelper.getVpnToExtrarouteVrfIdIdentifier(vpnName, usedRd, prefix));
654 confTx.delete(VpnExtraRouteHelper.getUsedRdsIdentifier(vpnId, prefix, nextHopRemoved));
661 private String getEndpointIpAddressForDPN(BigInteger dpnId) {
662 //TODO: Move it to a common place for vpn and fib
663 String nextHopIp = null;
664 InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
665 InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpnId)).build();
666 Optional<DPNTEPsInfo> tunnelInfo = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, tunnelInfoId);
667 if (tunnelInfo.isPresent()) {
668 List<TunnelEndPoints> nexthopIpList = tunnelInfo.get().getTunnelEndPoints();
669 if (nexthopIpList != null && !nexthopIpList.isEmpty()) {
670 nextHopIp = nexthopIpList.get(0).getIpAddress().stringValue();
676 public static String getIpPrefix(String prefix) {
677 String[] prefixValues = prefix.split(FibConstants.PREFIX_SEPARATOR);
678 if (prefixValues.length == 1) {
679 return NWUtil.toIpPrefix(prefix);
684 public static boolean isTunnelInterface(AdjacencyResult adjacencyResult) {
685 return Tunnel.class.equals(adjacencyResult.getInterfaceType());
688 public static InstanceIdentifier<VrfEntry> getNextHopIdentifier(String rd, String prefix) {
689 return InstanceIdentifier.builder(FibEntries.class)
690 .child(VrfTables.class,new VrfTablesKey(rd)).child(VrfEntry.class,new VrfEntryKey(prefix)).build();
693 public List<String> getNextHopAddresses(String rd, String prefix) {
694 InstanceIdentifier<VrfEntry> vrfEntryId = getNextHopIdentifier(rd, prefix);
695 Optional<VrfEntry> vrfEntry = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
696 if (vrfEntry.isPresent()) {
697 return FibHelper.getNextHopListFromRoutePaths(vrfEntry.get());
699 return Collections.emptyList();
703 public static String getGreLbGroupKey(List<String> availableDcGws) {
704 Preconditions.checkNotNull(availableDcGws, "AvailableDcGws is null");
705 return "gre-" + availableDcGws.stream().sorted().collect(joining(":"));
708 public static void updateLbGroupInfo(BigInteger dpnId, String destinationIp, String groupIdKey,
709 String groupId, TypedWriteTransaction<Operational> tx) {
710 InstanceIdentifier<DpnLbNexthops> id = getDpnLbNexthopsIdentifier(dpnId, destinationIp);
711 DpnLbNexthops dpnToLbNextHop = buildDpnLbNextHops(dpnId, destinationIp, groupIdKey);
712 tx.merge(id, dpnToLbNextHop);
713 InstanceIdentifier<Nexthops> nextHopsId = getNextHopsIdentifier(groupIdKey);
714 Nexthops nextHopsToGroupId = buildNextHops(dpnId, groupIdKey, groupId);
715 tx.merge(nextHopsId, nextHopsToGroupId);
718 public static void removeDpnIdToNextHopInfo(String destinationIp, BigInteger dpnId,
719 TypedWriteTransaction<Operational> tx) {
720 tx.delete(getDpnLbNexthopsIdentifier(dpnId, destinationIp));
723 public static void removeOrUpdateNextHopInfo(BigInteger dpnId, String nextHopKey, String groupId,
724 Nexthops nexthops, TypedWriteTransaction<Operational> tx) {
725 InstanceIdentifier<Nexthops> nextHopsId = getNextHopsIdentifier(nextHopKey);
726 List<String> targetDeviceIds = new ArrayList<>(nullToEmpty(nexthops.getTargetDeviceId()));
727 targetDeviceIds.remove(dpnId.toString());
728 if (targetDeviceIds.isEmpty()) {
729 tx.delete(nextHopsId);
731 Nexthops nextHopsToGroupId = new NexthopsBuilder().withKey(new NexthopsKey(nextHopKey))
732 .setNexthopKey(nextHopKey)
734 .setTargetDeviceId(targetDeviceIds).build();
735 tx.put(nextHopsId, nextHopsToGroupId);
739 private static InstanceIdentifier<DpnLbNexthops> getDpnLbNexthopsIdentifier(BigInteger dpnId,
740 String destinationIp) {
741 return InstanceIdentifier.builder(DpidL3vpnLbNexthops.class)
742 .child(DpnLbNexthops.class, new DpnLbNexthopsKey(destinationIp, dpnId))
746 private static InstanceIdentifier<Nexthops> getNextHopsIdentifier(String groupIdKey) {
747 return InstanceIdentifier.builder(L3vpnLbNexthops.class)
748 .child(Nexthops.class, new NexthopsKey(groupIdKey)).build();
751 private static Nexthops buildNextHops(BigInteger dpnId, String groupIdKey, String groupId) {
752 return new NexthopsBuilder().withKey(new NexthopsKey(groupIdKey))
753 .setNexthopKey(groupIdKey)
755 .setTargetDeviceId(Collections.singletonList(dpnId.toString())).build();
758 private static DpnLbNexthops buildDpnLbNextHops(BigInteger dpnId, String destinationIp,
760 return new DpnLbNexthopsBuilder().withKey(new DpnLbNexthopsKey(destinationIp, dpnId))
761 .setDstDeviceId(destinationIp).setSrcDpId(dpnId)
762 .setNexthopKey(Collections.singletonList(groupIdKey)).build();
765 public Optional<Nexthops> getNexthops(String nextHopKey) {
766 InstanceIdentifier<Nexthops> nextHopsId = InstanceIdentifier.builder(L3vpnLbNexthops.class)
767 .child(Nexthops.class, new NexthopsKey(nextHopKey)).build();
768 return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, nextHopsId);
771 public Optional<DpnLbNexthops> getDpnLbNexthops(BigInteger dpnId, String destinationIp) {
772 InstanceIdentifier<DpnLbNexthops> id = InstanceIdentifier.builder(DpidL3vpnLbNexthops.class)
773 .child(DpnLbNexthops.class, new DpnLbNexthopsKey(destinationIp, dpnId))
775 return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
778 static boolean isVxlanNetwork(NetworkType networkType) {
779 if (networkType != null) {
780 return networkType == NetworkAttributes.NetworkType.VXLAN;
785 static boolean isBgpVpn(String vpnName, String rd) {
786 return vpnName != null && !vpnName.equals(rd);
789 static NodeRef buildNodeRef(BigInteger dpId) {
790 return new NodeRef(InstanceIdentifier.builder(Nodes.class)
791 .child(Node.class, new NodeKey(new NodeId("openflow:" + dpId))).build());
794 static InstanceIdentifier<Group> buildGroupInstanceIdentifier(long groupId, BigInteger dpId) {
795 return InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(new NodeId("openflow:" + dpId)))
796 .augmentation(FlowCapableNode.class).child(Group.class, new GroupKey(new GroupId(groupId))).build();
799 static Buckets buildBuckets(List<BucketInfo> listBucketInfo) {
801 BucketsBuilder bucketsBuilder = new BucketsBuilder();
802 if (listBucketInfo != null) {
803 List<Bucket> bucketList = new ArrayList<>();
805 for (BucketInfo bucketInfo : listBucketInfo) {
806 BucketBuilder bucketBuilder = new BucketBuilder();
807 bucketBuilder.setAction(bucketInfo.buildActions());
808 bucketBuilder.setWeight(bucketInfo.getWeight());
809 bucketBuilder.setBucketId(new BucketId(index++));
810 bucketBuilder.setWeight(bucketInfo.getWeight()).setWatchPort(bucketInfo.getWatchPort())
811 .setWatchGroup(bucketInfo.getWatchGroup());
812 bucketList.add(bucketBuilder.build());
815 bucketsBuilder.setBucket(bucketList);
817 return bucketsBuilder.build();
820 static String getFlowRef(BigInteger dpnId, short tableId, long label, int priority) {
821 return FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId + NwConstants.FLOWID_SEPARATOR + label
822 + NwConstants.FLOWID_SEPARATOR + priority;
825 static String getFlowRef(BigInteger dpnId, short tableId, String rd, int priority, InetAddress destPrefix) {
826 return FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId + NwConstants.FLOWID_SEPARATOR + rd
827 + NwConstants.FLOWID_SEPARATOR + priority + NwConstants.FLOWID_SEPARATOR + destPrefix.getHostAddress();
830 static String getL3VpnGatewayFlowRef(short l3GwMacTable, BigInteger dpId, long vpnId, String gwMacAddress) {
831 return gwMacAddress + NwConstants.FLOWID_SEPARATOR + vpnId + NwConstants.FLOWID_SEPARATOR + dpId
832 + NwConstants.FLOWID_SEPARATOR + l3GwMacTable;
835 static Node buildDpnNode(BigInteger dpnId) {
836 return new NodeBuilder().setId(new NodeId("openflow:" + dpnId))
837 .withKey(new NodeKey(new NodeId("openflow:" + dpnId))).build();
840 public static String getBroadcastAddressFromCidr(String cidr) {
841 String[] ipaddressValues = cidr.split("/");
842 int address = InetAddresses.coerceToInteger(InetAddresses.forString(ipaddressValues[0]));
843 int cidrPart = Integer.parseInt(ipaddressValues[1]);
845 for (int j = 0; j < cidrPart; ++j) {
846 netmask |= 1 << 31 - j;
848 int network = address & netmask;
849 int broadcast = network | ~netmask;
850 return InetAddresses.toAddrString(InetAddresses.fromInteger(broadcast));
853 public static boolean lockCluster(LockManagerService lockManager, String lockName, long tryLockPeriod) {
854 TryLockInput input = new TryLockInputBuilder().setLockName(lockName).setTime(tryLockPeriod)
855 .setTimeUnit(TimeUnits.Milliseconds).build();
856 Future<RpcResult<TryLockOutput>> result = lockManager.tryLock(input);
857 boolean lockAcquired;
859 if (result != null && result.get().isSuccessful()) {
860 LOG.debug("lockCluster: Acquired lock for {}", lockName);
863 LOG.error("lockCluster: Unable to getLock for {}", lockName);
864 lockAcquired = false;
866 } catch (InterruptedException | ExecutionException e) {
867 LOG.error("lockCluster: Exception while trying to getLock for {}", lockName, e);
868 lockAcquired = false;
874 public static void unlockCluster(LockManagerService lockManager, String lockName) {
875 UnlockInput input = new UnlockInputBuilder().setLockName(lockName).build();
876 Future<RpcResult<UnlockOutput>> result = lockManager.unlock(input);
878 if (result != null && result.get().isSuccessful()) {
879 LOG.debug("unlockCluster: Unlocked {}", lockName);
881 LOG.error("unlockCluster: Unable to release lock for {}", lockName);
883 } catch (InterruptedException | ExecutionException e) {
884 LOG.error("unlockCluster: Unable to unlock {}", lockName, e);
888 public boolean isInterfacePresentInDpn(String vpnName, BigInteger dpnId) {
889 InstanceIdentifier<VpnToDpnList> vpnToDpnListId = InstanceIdentifier.builder(VpnInstanceOpData.class)
890 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vpnName))
891 .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
893 VpnToDpnList vpnToDpnList = SingleTransactionDataBroker.syncRead(dataBroker,
894 LogicalDatastoreType.OPERATIONAL, vpnToDpnListId);
895 if (!(vpnToDpnList == null) && !(vpnToDpnList.getVpnInterfaces() == null)
896 && !vpnToDpnList.getVpnInterfaces().isEmpty()) {
899 } catch (ReadFailedException e) {
900 LOG.warn("Failed to read interfaces with error {}", e.getMessage());
905 // TODO Replace this with mdsal's DataObjectUtils.nullToEmpty when upgrading to mdsal 3
907 public static <T> List<T> nullToEmpty(final @Nullable List<T> input) {
908 return input != null ? input : emptyList();