2 * Copyright (c) 2016 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 com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.CheckedFuture;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
19 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
22 import org.opendaylight.genius.mdsalutil.MDSALUtil;
23 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
24 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.RouterInterface;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
48 .VpnInstanceOpDataEntry;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
50 .VpnInstanceOpDataEntryKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinks;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn
59 .link.states.InterVpnLinkState;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn
61 .link.states.InterVpnLinkStateKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn
64 import org.opendaylight.yangtools.yang.binding.DataObject;
65 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
66 import org.opendaylight.yangtools.yang.common.RpcResult;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
70 import java.math.BigInteger;
71 import java.util.ArrayList;
72 import java.util.Arrays;
73 import java.util.List;
74 import java.util.concurrent.ExecutionException;
75 import java.util.concurrent.Future;
77 public class FibUtil {
78 private static final Logger LOG = LoggerFactory.getLogger(FibUtil.class);
79 public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
80 InstanceIdentifier<T> path) {
82 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
84 Optional<T> result = Optional.absent();
86 result = tx.read(datastoreType, path).get();
87 } catch (Exception e) {
88 throw new RuntimeException(e);
94 static <T extends DataObject> void asyncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
95 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
96 WriteTransaction tx = broker.newWriteOnlyTransaction();
97 tx.merge(datastoreType, path, data, true);
98 Futures.addCallback(tx.submit(), callback);
101 static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
102 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
103 WriteTransaction tx = broker.newWriteOnlyTransaction();
104 tx.put(datastoreType, path, data, true);
105 CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
108 } catch (InterruptedException | ExecutionException e) {
109 LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data, e);
110 throw new RuntimeException(e.getMessage());
114 static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
115 WriteTransaction tx = broker.newWriteOnlyTransaction();
116 tx.delete(datastoreType, path);
117 Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
120 static InstanceIdentifier<Adjacency> getAdjacencyIdentifier(String vpnInterfaceName, String ipAddress) {
121 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
122 .child(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface.class, new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey(vpnInterfaceName)).augmentation(
123 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies.class)
124 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey(ipAddress)).build();
127 static InstanceIdentifier<Adjacencies> getAdjListPath(String vpnInterfaceName) {
128 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
129 .child(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface.class, new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey(vpnInterfaceName)).augmentation(
130 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies.class).build();
133 static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
134 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PrefixToInterface.class)
135 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
136 .VpnIds.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIdsKey(vpnId)).child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes.class,
137 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey(ipPrefix)).build();
140 static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
141 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
142 .child(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface.class, new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey(vpnInterfaceName)).build();
145 public static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
146 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData.class)
147 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey(rd))
148 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey(dpnId)).build();
151 static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute> getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) {
152 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnToExtraroute.class)
153 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.Vpn
154 .class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to
155 .extraroute.VpnKey(vrfId)).child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn
156 .rev130911.vpn.to.extraroute.vpn.Extraroute.class,
157 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey(ipPrefix)).build();
160 static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
161 return InstanceIdentifier.builder(VpnInstanceOpData.class)
162 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
165 static Optional<VpnInstanceOpDataEntry> getVpnInstanceOpData(DataBroker broker, String rd) {
166 InstanceIdentifier<VpnInstanceOpDataEntry> id = getVpnInstanceOpDataIdentifier(rd);
167 return read(broker, LogicalDatastoreType.OPERATIONAL, id);
170 static String getNextHopLabelKey(String rd, String prefix){
171 String key = rd + FibConstants.SEPARATOR + prefix;
175 static Prefixes getPrefixToInterface(DataBroker broker, Long vpnId, String ipPrefix) {
176 Optional<Prefixes> localNextHopInfoData = read(broker, LogicalDatastoreType.OPERATIONAL,
177 getPrefixToInterfaceIdentifier(vpnId, ipPrefix));
178 return localNextHopInfoData.isPresent() ? localNextHopInfoData.get() : null;
181 static String getMacAddressFromPrefix(DataBroker broker, String ifName, String ipPrefix) {
182 Optional<Adjacency> adjacencyData = read(broker, LogicalDatastoreType.OPERATIONAL,
183 getAdjacencyIdentifier(ifName, ipPrefix));
184 return adjacencyData.isPresent() ? adjacencyData.get().getMacAddress() : null;
187 static void releaseId(IdManagerService idManager, String poolName, String idKey) {
188 ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
190 Future<RpcResult<Void>> result = idManager.releaseId(idInput);
191 RpcResult<Void> rpcResult = result.get();
192 if(!rpcResult.isSuccessful()) {
193 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
195 } catch (InterruptedException | ExecutionException e) {
196 LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
200 static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
201 getVpnInstanceToVpnIdIdentifier(String vpnName) {
202 return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
203 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
204 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
207 public static long getVpnId(DataBroker broker, String vpnName) {
209 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
211 = getVpnInstanceToVpnIdIdentifier(vpnName);
212 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
213 .VpnInstance> vpnInstance
214 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
217 if(vpnInstance.isPresent()) {
218 vpnId = vpnInstance.get().getVpnId();
224 * Retrieves the VpnInstance name (typically the VPN Uuid) out from the route-distinguisher
230 public static Optional<String> getVpnNameFromRd(DataBroker broker, String rd) {
231 Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = getVpnInstanceOpData(broker, rd);
232 return Optional.fromNullable(vpnInstanceOpData.isPresent() ? vpnInstanceOpData.get().getVpnInstanceName()
236 static List<InterVpnLink> getAllInterVpnLinks(DataBroker broker) {
237 InstanceIdentifier<InterVpnLinks> interVpnLinksIid = InstanceIdentifier.builder(InterVpnLinks.class).build();
239 Optional<InterVpnLinks> interVpnLinksOpData = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
242 return interVpnLinksOpData.isPresent() ? interVpnLinksOpData.get().getInterVpnLink()
247 * Returns the instance identifier for a given vpnLinkName
252 public static InstanceIdentifier<InterVpnLinkState> getInterVpnLinkStateIid(String vpnLinkName) {
253 return InstanceIdentifier.builder(InterVpnLinkStates.class).child(InterVpnLinkState.class, new InterVpnLinkStateKey(vpnLinkName)).build();
257 * Checks if the InterVpnLink is in Active state
263 public static boolean isInterVpnLinkActive(DataBroker broker, String vpnLinkName) {
264 Optional<InterVpnLinkState> interVpnLinkState = getInterVpnLinkState(broker, vpnLinkName);
265 if ( !interVpnLinkState.isPresent() ) {
266 LOG.warn("Could not find Operative State for InterVpnLink {}", vpnLinkName);
270 return interVpnLinkState.get().getState().equals(InterVpnLinkState.State.Active);
274 * Checks if the state of the interVpnLink
280 public static Optional<InterVpnLinkState> getInterVpnLinkState(DataBroker broker, String vpnLinkName) {
281 InstanceIdentifier<InterVpnLinkState> vpnLinkStateIid = getInterVpnLinkStateIid(vpnLinkName);
282 return read(broker, LogicalDatastoreType.CONFIGURATION, vpnLinkStateIid);
286 * Retrieves the InterVpnLink in which the VPN, represented by its Uuid,
291 * @return The InterVpnLink or Optional.absent() if the VPN does not
292 * participate in an InterVpnLink
294 public static Optional<InterVpnLink> getInterVpnLinkByVpnUuid(DataBroker dataBroker, String vpnUuid) {
295 List<InterVpnLink> interVpnLinkList = getAllInterVpnLinks(dataBroker);
296 for (InterVpnLink interVpnLink : interVpnLinkList) {
297 if (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(vpnUuid)
298 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(vpnUuid)) {
299 LOG.debug("InterVpnLink found for VPN {}. Details: vpn1=( uuid={} endpoint={}) vpn2=( uuid={} endpoint={} ))",
300 vpnUuid, interVpnLink.getFirstEndpoint().getVpnUuid(),
301 interVpnLink.getFirstEndpoint().getIpAddress(), interVpnLink.getSecondEndpoint().getVpnUuid(),
302 interVpnLink.getSecondEndpoint().getIpAddress());
303 return Optional.fromNullable(interVpnLink);
306 LOG.debug("Could not find a suitable InterVpnLink for VpnUuid={}", vpnUuid);
307 return Optional.absent();
311 * Retrieves the InterVpnLink in which the VPN, represented by its
312 * Route-Distinguisher, participates.
316 * @return The InterVpnLink or Optional.absent() if the VPN does not
317 * participate in an InterVpnLink
319 public static Optional<InterVpnLink> getInterVpnLinkByRd(DataBroker dataBroker, String rd) {
320 Optional<String> vpnId = getVpnNameFromRd(dataBroker, rd);
321 if ( !vpnId.isPresent() ) {
322 LOG.debug("Could not find vpnId for RouteDistinguisher {}", rd);
323 return Optional.absent();
326 return getInterVpnLinkByVpnUuid(dataBroker, vpnId.get());
330 * Checks if the route-distinguisher is involved in any inter-vpn-link, which is returned if its found.
336 public static Optional<InterVpnLink> getActiveInterVpnLinkFromRd(DataBroker dataBroker, String rd) {
338 Optional<InterVpnLink> interVpnLink = getInterVpnLinkByRd(dataBroker, rd);
339 if ( interVpnLink.isPresent() ) {
340 if ( isInterVpnLinkActive(dataBroker, interVpnLink.get().getName()) ) {
343 LOG.warn("InterVpnLink for RouteDistinguisher {} exists, but it's in error state. InterVpnLink={}",
344 rd, interVpnLink.get().getName());
345 return Optional.absent();
348 return Optional.absent();
352 * Checks if the route-distinguisher is involved in any inter-vpn-link. In that case, this method will return
353 * the endpoint of the other vpn involved in the inter-vpn-link.
359 public static Optional<String> getInterVpnLinkOppositeEndPointIpAddress(DataBroker dataBroker, String rd) {
360 Optional<String> vpnId = getVpnNameFromRd(dataBroker, rd);
361 if ( !vpnId.isPresent() ) {
362 LOG.debug("Could not find the VpnName for RouteDistinguisher {}", rd);
363 return Optional.absent();
365 List<InterVpnLink> interVpnLinkList = getAllInterVpnLinks(dataBroker);
366 if (!interVpnLinkList.isEmpty()) {
367 for (InterVpnLink interVpnLink : interVpnLinkList) {
368 if (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(vpnId)) {
369 return Optional.fromNullable(interVpnLink.getSecondEndpoint().getVpnUuid().getValue());
370 } else if (interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(vpnId)) {
371 return Optional.fromNullable(interVpnLink.getFirstEndpoint().getIpAddress().getValue());
375 return Optional.absent();
379 * Obtains the route-distinguisher for a given vpn-name
385 public static String getVpnRd(DataBroker broker, String vpnName) {
386 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
388 = getVpnInstanceToVpnIdIdentifier(vpnName);
389 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
390 .VpnInstance> vpnInstance
391 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
394 if(vpnInstance.isPresent()) {
395 rd = vpnInstance.get().getVrfId();
401 * Returns a boolean value which indicates if the endpoint's IP received as parameter belongs to any InterVpnLink.
404 * @param endpointIp IP to serch for.
407 public static boolean getInterVpnLinkByEndpointIp(DataBroker broker, String endpointIp) {
408 List<InterVpnLink> allInterVpnLinks = getAllInterVpnLinks(broker);
409 for (InterVpnLink interVpnLink : allInterVpnLinks) {
410 if (interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(endpointIp)
411 || interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(endpointIp)) {
418 public static int getUniqueId(IdManagerService idManager, String poolName, String idKey) {
419 AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
422 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
423 RpcResult<AllocateIdOutput> rpcResult = result.get();
424 if (rpcResult.isSuccessful()) {
425 return rpcResult.getResult().getIdValue().intValue();
427 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
429 } catch (InterruptedException | ExecutionException e) {
430 LOG.warn("Exception when getting Unique Id", e);
435 static final FutureCallback<Void> DEFAULT_CALLBACK =
436 new FutureCallback<Void>() {
438 public void onSuccess(Void result) {
439 LOG.debug("Success in Datastore operation");
443 public void onFailure(Throwable error) {
444 LOG.error("Error in Datastore operation", error);
448 public static String getVpnNameFromId(DataBroker broker, long vpnId) {
450 InstanceIdentifier<VpnIds> id
451 = getVpnIdToVpnInstanceIdentifier(vpnId);
452 Optional<VpnIds> vpnInstance
453 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
455 String vpnName = null;
456 if (vpnInstance.isPresent()) {
457 vpnName = vpnInstance.get().getVpnInstanceName();
462 static InstanceIdentifier<VpnIds>
463 getVpnIdToVpnInstanceIdentifier(long vpnId) {
464 return InstanceIdentifier.builder(VpnIdToVpnInstance.class)
465 .child(VpnIds.class, new VpnIdsKey(Long.valueOf(vpnId))).build();
468 public static <T extends DataObject> void syncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
469 InstanceIdentifier<T> path, T data) {
470 WriteTransaction tx = broker.newWriteOnlyTransaction();
471 tx.put(datastoreType, path, data, true);
472 CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
475 } catch (InterruptedException | ExecutionException e) {
476 LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data, e);
477 throw new RuntimeException(e.getMessage());
481 public static void addOrUpdateFibEntry(DataBroker broker, String rd, String prefix, List<String> nextHopList,
482 int label, RouteOrigin origin, WriteTransaction writeConfigTxn) {
483 if (rd == null || rd.isEmpty() ) {
484 LOG.error("Prefix {} not associated with vpn", prefix);
488 Preconditions.checkNotNull(nextHopList, "NextHopList can't be null");
491 InstanceIdentifier<VrfEntry> vrfEntryId =
492 InstanceIdentifier.builder(FibEntries.class)
493 .child(VrfTables.class, new VrfTablesKey(rd))
494 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
495 Optional<VrfEntry> entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
497 if (! entry.isPresent()) {
498 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(nextHopList)
499 .setLabel((long)label).setOrigin(origin.getValue()).build();
501 if (writeConfigTxn != null) {
502 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
504 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
506 LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nextHopList, label);
507 } else { // Found in MDSAL database
508 List<String> nh = entry.get().getNextHopAddressList();
509 for (String nextHop : nextHopList) {
510 if (!nh.contains(nextHop)) {
514 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(nh)
515 .setLabel((long) label).setOrigin(origin.getValue()).build();
517 if (writeConfigTxn != null) {
518 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
520 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
522 LOG.debug("Updated vrfEntry for {} nexthop {} label {}", prefix, nh, label);
524 } catch (Exception e) {
525 LOG.error("addFibEntryToDS: error ", e);
529 public static void addFibEntryForRouterInterface(DataBroker broker,
532 RouterInterface routerInterface,
534 WriteTransaction writeConfigTxn) {
535 if (rd == null || rd.isEmpty() ) {
536 LOG.error("Prefix {} not associated with vpn", prefix);
541 InstanceIdentifier<VrfEntry> vrfEntryId =
542 InstanceIdentifier.builder(FibEntries.class)
543 .child(VrfTables.class, new VrfTablesKey(rd))
544 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
546 VrfEntry vrfEntry = new VrfEntryBuilder().setKey(new VrfEntryKey(prefix)).setDestPrefix(prefix)
547 .setNextHopAddressList(Arrays.asList(""))
549 .setOrigin(RouteOrigin.LOCAL.getValue())
550 .addAugmentation(RouterInterface.class, routerInterface).build();
552 if (writeConfigTxn != null) {
553 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
555 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
557 LOG.debug("Created vrfEntry for router-interface-prefix {} rd {} label {}", prefix, rd, label);
558 } catch (Exception e) {
559 LOG.error("addFibEntryToDS: error ", e);
563 public static void removeFibEntry(DataBroker broker, String rd, String prefix, WriteTransaction writeConfigTxn) {
565 if (rd == null || rd.isEmpty()) {
566 LOG.error("Prefix {} not associated with vpn", prefix);
569 LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
571 InstanceIdentifier.InstanceIdentifierBuilder<VrfEntry> idBuilder =
572 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix));
573 InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
574 if (writeConfigTxn != null) {
575 writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
577 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
582 * Removes a specific Nexthop from a VrfEntry. If Nexthop to remove is the
583 * last one in the VrfEntry, then the VrfEntry is removed too.
585 * @param broker dataBroker service reference
586 * @param rd Route-Distinguisher to which the VrfEntry belongs to
587 * @param prefix Destination of the route
588 * @param nextHopToRemove Specific nexthop within the Route to be removed.
589 * If null or empty, then the whole VrfEntry is removed
591 public static void removeOrUpdateFibEntry(DataBroker broker, String rd, String prefix, String nextHopToRemove,
592 WriteTransaction writeConfigTxn) {
594 LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
596 // Looking for existing prefix in MDSAL database
597 InstanceIdentifier<VrfEntry> vrfEntryId =
598 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
599 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
600 Optional<VrfEntry> entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
602 if ( entry.isPresent() ) {
603 List<String> nhListRead = new ArrayList<>();
604 if ( nextHopToRemove != null && !nextHopToRemove.isEmpty()) {
605 nhListRead = entry.get().getNextHopAddressList();
606 if (nhListRead.contains(nextHopToRemove)) {
607 nhListRead.remove(nextHopToRemove);
611 if (nhListRead.isEmpty()) {
612 // Remove the whole entry
613 if (writeConfigTxn != null) {
614 writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
616 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
618 LOG.info("Removed Fib Entry rd {} prefix {}", rd, prefix);
620 // An update must be done, not including the current next hop
622 new VrfEntryBuilder(entry.get()).setDestPrefix(prefix).setNextHopAddressList(nhListRead)
623 .setKey(new VrfEntryKey(prefix)).build();
624 if (writeConfigTxn != null) {
625 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
627 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
629 LOG.info("Removed Nexthop {} from Fib Entry rd {} prefix {}", nextHopToRemove, rd, prefix);
632 LOG.warn("Could not find VrfEntry for Route-Distinguisher={} and prefix={}", rd, prefix);
636 public static void updateFibEntry(DataBroker broker, String rd, String prefix, List<String> nextHopList,
637 WriteTransaction writeConfigTxn) {
639 LOG.debug("Updating fib entry for prefix {} with nextHopList {} for rd {}", prefix, nextHopList, rd);
641 // Looking for existing prefix in MDSAL database
642 InstanceIdentifier<VrfEntry> vrfEntryId =
643 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
644 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
645 Optional<VrfEntry> entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
647 if ( entry.isPresent() ) {
648 // Update the VRF entry with nextHopList
650 new VrfEntryBuilder(entry.get()).setDestPrefix(prefix).setNextHopAddressList(nextHopList)
651 .setKey(new VrfEntryKey(prefix)).build();
652 if(nextHopList.isEmpty()) {
653 if (writeConfigTxn != null) {
654 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
656 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
659 if (writeConfigTxn != null) {
660 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true);
662 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
665 LOG.debug("Updated fib entry for prefix {} with nextHopList {} for rd {}", prefix, nextHopList, rd);
667 LOG.warn("Could not find VrfEntry for Route-Distinguisher={} and prefix={}", rd, prefix);
671 public static void addVrfTable(DataBroker broker, String rd, WriteTransaction writeConfigTxn) {
672 LOG.debug("Adding vrf table for rd {}", rd);
673 InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder =
674 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
675 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
676 VrfTablesBuilder vrfTablesBuilder = new VrfTablesBuilder().setKey(new VrfTablesKey(rd)).setRouteDistinguisher(rd).setVrfEntry(new ArrayList<VrfEntry>());
677 if (writeConfigTxn != null) {
678 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTablesBuilder.build());
680 syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTablesBuilder.build(), FibUtil.DEFAULT_CALLBACK);
685 public static void removeVrfTable(DataBroker broker, String rd, WriteTransaction writeConfigTxn) {
686 LOG.debug("Removing vrf table for rd {}", rd);
687 InstanceIdentifier.InstanceIdentifierBuilder<VrfTables> idBuilder =
688 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
689 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
691 if (writeConfigTxn != null) {
692 writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, vrfTableId);
694 delete(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId);
698 public static boolean isControllerManagedRoute(RouteOrigin routeOrigin) {
699 if (routeOrigin == RouteOrigin.STATIC ||
700 routeOrigin == RouteOrigin.CONNECTED ||
701 routeOrigin == RouteOrigin.LOCAL ||
702 routeOrigin == RouteOrigin.INTERVPN) {
708 public static boolean isControllerManagedNonInterVpnLinkRoute(RouteOrigin routeOrigin)
710 if (routeOrigin == RouteOrigin.STATIC ||
711 routeOrigin == RouteOrigin.CONNECTED ||
712 routeOrigin == RouteOrigin.LOCAL) {