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.util.concurrent.CheckedFuture;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
18 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
21 import org.opendaylight.genius.mdsalutil.MDSALUtil;
22 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.*;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
33 .VpnInstanceOpDataEntry;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
35 .VpnInstanceOpDataEntryKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinks;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn
44 .link.states.InterVpnLinkState;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn
46 .link.states.InterVpnLinkStateKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn
49 import org.opendaylight.yangtools.yang.binding.DataObject;
50 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
51 import org.opendaylight.yangtools.yang.common.RpcResult;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
55 import java.math.BigInteger;
56 import java.util.ArrayList;
57 import java.util.List;
58 import java.util.concurrent.ExecutionException;
59 import java.util.concurrent.Future;
61 public class FibUtil {
62 private static final Logger LOG = LoggerFactory.getLogger(FibUtil.class);
63 public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
64 InstanceIdentifier<T> path) {
66 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
68 Optional<T> result = Optional.absent();
70 result = tx.read(datastoreType, path).get();
71 } catch (Exception e) {
72 throw new RuntimeException(e);
78 static <T extends DataObject> void asyncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
79 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
80 WriteTransaction tx = broker.newWriteOnlyTransaction();
81 tx.merge(datastoreType, path, data, true);
82 Futures.addCallback(tx.submit(), callback);
85 static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
86 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
87 WriteTransaction tx = broker.newWriteOnlyTransaction();
88 tx.put(datastoreType, path, data, true);
89 CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
92 } catch (InterruptedException | ExecutionException e) {
93 LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
94 throw new RuntimeException(e.getMessage());
98 static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
99 WriteTransaction tx = broker.newWriteOnlyTransaction();
100 tx.delete(datastoreType, path);
101 Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
104 static InstanceIdentifier<Adjacency> getAdjacencyIdentifier(String vpnInterfaceName, String ipAddress) {
105 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
106 .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(
107 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies.class)
108 .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();
111 static InstanceIdentifier<Adjacencies> getAdjListPath(String vpnInterfaceName) {
112 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
113 .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(
114 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies.class).build();
117 static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
118 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PrefixToInterface.class)
119 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
120 .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,
121 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey(ipPrefix)).build();
124 static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
125 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
126 .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();
129 public static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
130 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData.class)
131 .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))
132 .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();
135 static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute> getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) {
136 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnToExtraroute.class)
137 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.Vpn
138 .class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to
139 .extraroute.VpnKey(vrfId)).child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn
140 .rev130911.vpn.to.extraroute.vpn.Extraroute.class,
141 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey(ipPrefix)).build();
144 static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
145 return InstanceIdentifier.builder(VpnInstanceOpData.class)
146 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
149 static Optional<VpnInstanceOpDataEntry> getVpnInstanceOpData(DataBroker broker, String rd) {
150 InstanceIdentifier<VpnInstanceOpDataEntry> id = getVpnInstanceOpDataIdentifier(rd);
151 return read(broker, LogicalDatastoreType.OPERATIONAL, id);
154 static String getNextHopLabelKey(String rd, String prefix){
155 String key = rd + FibConstants.SEPARATOR + prefix;
159 static void releaseId(IdManagerService idManager, String poolName, String idKey) {
160 ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
162 Future<RpcResult<Void>> result = idManager.releaseId(idInput);
163 RpcResult<Void> rpcResult = result.get();
164 if(!rpcResult.isSuccessful()) {
165 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
167 } catch (InterruptedException | ExecutionException e) {
168 LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
172 static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
173 getVpnInstanceToVpnIdIdentifier(String vpnName) {
174 return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
175 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
176 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
179 public static long getVpnId(DataBroker broker, String vpnName) {
181 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
183 = getVpnInstanceToVpnIdIdentifier(vpnName);
184 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
185 .VpnInstance> vpnInstance
186 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
189 if(vpnInstance.isPresent()) {
190 vpnId = vpnInstance.get().getVpnId();
196 * Retrieves the VpnInstance name (typically the VPN Uuid) out from the route-distinguisher
202 public static Optional<String> getVpnNameFromRd(DataBroker broker, String rd) {
203 Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = getVpnInstanceOpData(broker, rd);
204 return Optional.fromNullable(vpnInstanceOpData.isPresent() ? vpnInstanceOpData.get().getVpnInstanceName()
208 static List<InterVpnLink> getAllInterVpnLinks(DataBroker broker) {
209 InstanceIdentifier<InterVpnLinks> interVpnLinksIid = InstanceIdentifier.builder(InterVpnLinks.class).build();
211 Optional<InterVpnLinks> interVpnLinksOpData = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
214 return ( interVpnLinksOpData.isPresent() ) ? interVpnLinksOpData.get().getInterVpnLink()
215 : new ArrayList<InterVpnLink>();
219 * Returns the instance identifier for a given vpnLinkName
224 public static InstanceIdentifier<InterVpnLinkState> getInterVpnLinkStateIid(String vpnLinkName) {
225 return InstanceIdentifier.builder(InterVpnLinkStates.class).child(InterVpnLinkState.class, new InterVpnLinkStateKey(vpnLinkName)).build();
229 * Checks if the InterVpnLink is in Active state
235 public static boolean isInterVpnLinkActive(DataBroker broker, String vpnLinkName) {
236 Optional<InterVpnLinkState> interVpnLinkState = getInterVpnLinkState(broker, vpnLinkName);
237 if ( !interVpnLinkState.isPresent() ) {
238 LOG.warn("Could not find Operative State for InterVpnLink {}", vpnLinkName);
242 return interVpnLinkState.get().getState().equals(InterVpnLinkState.State.Active);
246 * Checks if the state of the interVpnLink
252 public static Optional<InterVpnLinkState> getInterVpnLinkState(DataBroker broker, String vpnLinkName) {
253 InstanceIdentifier<InterVpnLinkState> vpnLinkStateIid = getInterVpnLinkStateIid(vpnLinkName);
254 return read(broker, LogicalDatastoreType.CONFIGURATION, vpnLinkStateIid);
258 * Retrieves the InterVpnLink in which the VPN, represented by its Uuid,
263 * @return The InterVpnLink or Optional.absent() if the VPN does not
264 * participate in an InterVpnLink
266 public static Optional<InterVpnLink> getInterVpnLinkByVpnUuid(DataBroker dataBroker, String vpnUuid) {
267 List<InterVpnLink> interVpnLinkList = getAllInterVpnLinks(dataBroker);
268 for (InterVpnLink interVpnLink : interVpnLinkList) {
269 if (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(vpnUuid)
270 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(vpnUuid)) {
271 LOG.debug("InterVpnLink found for VPN {}. Details: vpn1=( uuid={} endpoint={}) vpn2=( uuid={} endpoint={} ))",
272 vpnUuid, interVpnLink.getFirstEndpoint().getVpnUuid(),
273 interVpnLink.getFirstEndpoint().getIpAddress(), interVpnLink.getSecondEndpoint().getVpnUuid(),
274 interVpnLink.getSecondEndpoint().getIpAddress());
275 return Optional.fromNullable(interVpnLink);
278 LOG.debug("Could not find a suitable InterVpnLink for VpnUuid={}", vpnUuid);
279 return Optional.absent();
283 * Retrieves the InterVpnLink in which the VPN, represented by its
284 * Route-Distinguisher, participates.
288 * @return The InterVpnLink or Optional.absent() if the VPN does not
289 * participate in an InterVpnLink
291 public static Optional<InterVpnLink> getInterVpnLinkByRd(DataBroker dataBroker, String rd) {
292 Optional<String> vpnId = getVpnNameFromRd(dataBroker, rd);
293 if ( !vpnId.isPresent() ) {
294 LOG.debug("Could not find vpnId for RouteDistinguisher {}", rd);
295 return Optional.absent();
298 return getInterVpnLinkByVpnUuid(dataBroker, vpnId.get());
302 * Checks if the route-distinguisher is involved in any inter-vpn-link, which is returned if its found.
308 public static Optional<InterVpnLink> getActiveInterVpnLinkFromRd(DataBroker dataBroker, String rd) {
310 Optional<InterVpnLink> interVpnLink = getInterVpnLinkByRd(dataBroker, rd);
311 if ( interVpnLink.isPresent() ) {
312 if ( isInterVpnLinkActive(dataBroker, interVpnLink.get().getName()) ) {
315 LOG.warn("InterVpnLink for RouteDistinguisher {} exists, but it's in error state. InterVpnLink={}",
316 rd, interVpnLink.get().getName());
317 return Optional.absent();
320 return Optional.absent();
324 * Checks if the route-distinguisher is involved in any inter-vpn-link. In that case, this method will return
325 * the endpoint of the other vpn involved in the inter-vpn-link.
331 public static Optional<String> getInterVpnLinkOppositeEndPointIpAddress(DataBroker dataBroker, String rd) {
332 Optional<String> vpnId = getVpnNameFromRd(dataBroker, rd);
333 if ( !vpnId.isPresent() ) {
334 LOG.debug("Could not find the VpnName for RouteDistinguisher {}", rd);
335 return Optional.absent();
337 List<InterVpnLink> interVpnLinkList = getAllInterVpnLinks(dataBroker);
338 if (!interVpnLinkList.isEmpty()) {
339 for (InterVpnLink interVpnLink : interVpnLinkList) {
340 if (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(vpnId)) {
341 return Optional.fromNullable(interVpnLink.getSecondEndpoint().getVpnUuid().getValue());
342 } else if (interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(vpnId)) {
343 return Optional.fromNullable(interVpnLink.getFirstEndpoint().getIpAddress().getValue());
347 return Optional.absent();
351 * Obtains the route-distinguisher for a given vpn-name
357 public static String getVpnRd(DataBroker broker, String vpnName) {
358 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
360 = getVpnInstanceToVpnIdIdentifier(vpnName);
361 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
362 .VpnInstance> vpnInstance
363 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
366 if(vpnInstance.isPresent()) {
367 rd = vpnInstance.get().getVrfId();
373 * Returns a boolean value which indicates if the endpoint's IP received as parameter belongs to any InterVpnLink.
376 * @param endpointIp IP to serch for.
379 public static boolean getInterVpnLinkByEndpointIp(DataBroker broker, String endpointIp) {
380 List<InterVpnLink> allInterVpnLinks = getAllInterVpnLinks(broker);
381 for (InterVpnLink interVpnLink : allInterVpnLinks) {
382 if (interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(endpointIp)
383 || interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(endpointIp)) {
390 public static int getUniqueId(IdManagerService idManager, String poolName, String idKey) {
391 AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
394 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
395 RpcResult<AllocateIdOutput> rpcResult = result.get();
396 if (rpcResult.isSuccessful()) {
397 return rpcResult.getResult().getIdValue().intValue();
399 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
401 } catch (InterruptedException | ExecutionException e) {
402 LOG.warn("Exception when getting Unique Id", e);
407 static final FutureCallback<Void> DEFAULT_CALLBACK =
408 new FutureCallback<Void>() {
410 public void onSuccess(Void result) {
411 LOG.debug("Success in Datastore operation");
415 public void onFailure(Throwable error) {
416 LOG.error("Error in Datastore operation", error);
420 public static String getVpnNameFromId(DataBroker broker, long vpnId) {
422 InstanceIdentifier<VpnIds> id
423 = getVpnIdToVpnInstanceIdentifier(vpnId);
424 Optional<VpnIds> vpnInstance
425 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
427 String vpnName = null;
428 if (vpnInstance.isPresent()) {
429 vpnName = vpnInstance.get().getVpnInstanceName();
434 static InstanceIdentifier<VpnIds>
435 getVpnIdToVpnInstanceIdentifier(long vpnId) {
436 return InstanceIdentifier.builder(VpnIdToVpnInstance.class)
437 .child(VpnIds.class, new VpnIdsKey(Long.valueOf(vpnId))).build();
440 public static <T extends DataObject> void syncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
441 InstanceIdentifier<T> path, T data) {
442 WriteTransaction tx = broker.newWriteOnlyTransaction();
443 tx.put(datastoreType, path, data, true);
444 CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
447 } catch (InterruptedException | ExecutionException e) {
448 LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
449 throw new RuntimeException(e.getMessage());