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.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
17 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.genius.mdsalutil.MDSALUtil;
20 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.*;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
28 .VpnInstanceOpDataEntry;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
30 .VpnInstanceOpDataEntryKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinks;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn
39 .link.states.InterVpnLinkState;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn
41 .link.states.InterVpnLinkStateKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn
44 import org.opendaylight.yangtools.yang.binding.DataObject;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
46 import org.opendaylight.yangtools.yang.common.RpcResult;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
50 import java.math.BigInteger;
51 import java.util.ArrayList;
52 import java.util.List;
53 import java.util.concurrent.ExecutionException;
54 import java.util.concurrent.Future;
56 public class FibUtil {
57 private static final Logger LOG = LoggerFactory.getLogger(FibUtil.class);
58 public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
59 InstanceIdentifier<T> path) {
61 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
63 Optional<T> result = Optional.absent();
65 result = tx.read(datastoreType, path).get();
66 } catch (Exception e) {
67 throw new RuntimeException(e);
73 static <T extends DataObject> void asyncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
74 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
75 WriteTransaction tx = broker.newWriteOnlyTransaction();
76 tx.merge(datastoreType, path, data, true);
77 Futures.addCallback(tx.submit(), callback);
80 static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
81 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
82 WriteTransaction tx = broker.newWriteOnlyTransaction();
83 tx.merge(datastoreType, path, data, true);
87 static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
88 WriteTransaction tx = broker.newWriteOnlyTransaction();
89 tx.delete(datastoreType, path);
90 Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
93 static InstanceIdentifier<Adjacency> getAdjacencyIdentifier(String vpnInterfaceName, String ipAddress) {
94 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
95 .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(
96 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies.class)
97 .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();
100 static InstanceIdentifier<Adjacencies> getAdjListPath(String vpnInterfaceName) {
101 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
102 .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(
103 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies.class).build();
106 static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
107 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PrefixToInterface.class)
108 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface
109 .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,
110 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey(ipPrefix)).build();
113 static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
114 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
115 .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();
118 public static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
119 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData.class)
120 .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))
121 .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();
124 static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute> getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) {
125 return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnToExtraroute.class)
126 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.Vpn
127 .class, new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to
128 .extraroute.VpnKey(vrfId)).child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn
129 .rev130911.vpn.to.extraroute.vpn.Extraroute.class,
130 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey(ipPrefix)).build();
133 static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
134 return InstanceIdentifier.builder(VpnInstanceOpData.class)
135 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
138 static Optional<VpnInstanceOpDataEntry> getVpnInstanceOpData(DataBroker broker, String rd) {
139 InstanceIdentifier<VpnInstanceOpDataEntry> id = getVpnInstanceOpDataIdentifier(rd);
140 return read(broker, LogicalDatastoreType.OPERATIONAL, id);
143 static String getNextHopLabelKey(String rd, String prefix){
144 String key = rd + FibConstants.SEPARATOR + prefix;
148 static void releaseId(IdManagerService idManager, String poolName, String idKey) {
149 ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
151 Future<RpcResult<Void>> result = idManager.releaseId(idInput);
152 RpcResult<Void> rpcResult = result.get();
153 if(!rpcResult.isSuccessful()) {
154 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
156 } catch (InterruptedException | ExecutionException e) {
157 LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
161 static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
162 getVpnInstanceToVpnIdIdentifier(String vpnName) {
163 return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
164 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
165 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
168 public static long getVpnId(DataBroker broker, String vpnName) {
170 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
172 = getVpnInstanceToVpnIdIdentifier(vpnName);
173 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
174 .VpnInstance> vpnInstance
175 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
178 if(vpnInstance.isPresent()) {
179 vpnId = vpnInstance.get().getVpnId();
185 * Retrieves the VpnInstance name (typically the VPN Uuid) out from the route-distinguisher
191 public static Optional<String> getVpnNameFromRd(DataBroker broker, String rd) {
192 Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = getVpnInstanceOpData(broker, rd);
193 return Optional.fromNullable(vpnInstanceOpData.isPresent() ? vpnInstanceOpData.get().getVpnInstanceName()
197 static List<InterVpnLink> getAllInterVpnLinks(DataBroker broker) {
198 InstanceIdentifier<InterVpnLinks> interVpnLinksIid = InstanceIdentifier.builder(InterVpnLinks.class).build();
200 Optional<InterVpnLinks> interVpnLinksOpData = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
203 return ( interVpnLinksOpData.isPresent() ) ? interVpnLinksOpData.get().getInterVpnLink()
204 : new ArrayList<InterVpnLink>();
208 * Returns the instance identifier for a given vpnLinkName
213 public static InstanceIdentifier<InterVpnLinkState> getInterVpnLinkStateIid(String vpnLinkName) {
214 return InstanceIdentifier.builder(InterVpnLinkStates.class).child(InterVpnLinkState.class, new InterVpnLinkStateKey(vpnLinkName)).build();
218 * Checks if the InterVpnLink is in Active state
224 public static boolean isInterVpnLinkActive(DataBroker broker, String vpnLinkName) {
225 Optional<InterVpnLinkState> interVpnLinkState = getInterVpnLinkState(broker, vpnLinkName);
226 if ( !interVpnLinkState.isPresent() ) {
227 LOG.warn("Could not find Operative State for InterVpnLink {}", vpnLinkName);
231 return interVpnLinkState.get().getState().equals(InterVpnLinkState.State.Active);
235 * Checks if the state of the interVpnLink
241 public static Optional<InterVpnLinkState> getInterVpnLinkState(DataBroker broker, String vpnLinkName) {
242 InstanceIdentifier<InterVpnLinkState> vpnLinkStateIid = getInterVpnLinkStateIid(vpnLinkName);
243 return read(broker, LogicalDatastoreType.CONFIGURATION, vpnLinkStateIid);
247 * Retrieves the InterVpnLink in which the VPN, represented by its Uuid,
252 * @return The InterVpnLink or Optional.absent() if the VPN does not
253 * participate in an InterVpnLink
255 public static Optional<InterVpnLink> getInterVpnLinkByVpnUuid(DataBroker dataBroker, String vpnUuid) {
256 List<InterVpnLink> interVpnLinkList = getAllInterVpnLinks(dataBroker);
257 for (InterVpnLink interVpnLink : interVpnLinkList) {
258 if (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(vpnUuid)
259 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(vpnUuid)) {
260 LOG.debug("InterVpnLink found for VPN {}. Details: vpn1=( uuid={} endpoint={}) vpn2=( uuid={} endpoint={} ))",
261 vpnUuid, interVpnLink.getFirstEndpoint().getVpnUuid(),
262 interVpnLink.getFirstEndpoint().getIpAddress(), interVpnLink.getSecondEndpoint().getVpnUuid(),
263 interVpnLink.getSecondEndpoint().getIpAddress());
264 return Optional.fromNullable(interVpnLink);
267 LOG.debug("Could not find a suitable InterVpnLink for VpnUuid={}", vpnUuid);
268 return Optional.absent();
272 * Retrieves the InterVpnLink in which the VPN, represented by its
273 * Route-Distinguisher, participates.
277 * @return The InterVpnLink or Optional.absent() if the VPN does not
278 * participate in an InterVpnLink
280 public static Optional<InterVpnLink> getInterVpnLinkByRd(DataBroker dataBroker, String rd) {
281 Optional<String> vpnId = getVpnNameFromRd(dataBroker, rd);
282 if ( !vpnId.isPresent() ) {
283 LOG.debug("Could not find vpnId for RouteDistinguisher {}", rd);
284 return Optional.absent();
287 return getInterVpnLinkByVpnUuid(dataBroker, vpnId.get());
291 * Checks if the route-distinguisher is involved in any inter-vpn-link, which is returned if its found.
297 public static Optional<InterVpnLink> getActiveInterVpnLinkFromRd(DataBroker dataBroker, String rd) {
299 Optional<InterVpnLink> interVpnLink = getInterVpnLinkByRd(dataBroker, rd);
300 if ( interVpnLink.isPresent() ) {
301 if ( isInterVpnLinkActive(dataBroker, interVpnLink.get().getName()) ) {
304 LOG.warn("InterVpnLink for RouteDistinguisher {} exists, but it's in error state. InterVpnLink={}",
305 rd, interVpnLink.get().getName());
306 return Optional.absent();
309 return Optional.absent();
313 * Checks if the route-distinguisher is involved in any inter-vpn-link. In that case, this method will return
314 * the endpoint of the other vpn involved in the inter-vpn-link.
320 public static Optional<String> getInterVpnLinkOppositeEndPointIpAddress(DataBroker dataBroker, String rd) {
321 Optional<String> vpnId = getVpnNameFromRd(dataBroker, rd);
322 if ( !vpnId.isPresent() ) {
323 LOG.debug("Could not find the VpnName for RouteDistinguisher {}", rd);
324 return Optional.absent();
326 List<InterVpnLink> interVpnLinkList = getAllInterVpnLinks(dataBroker);
327 if (!interVpnLinkList.isEmpty()) {
328 for (InterVpnLink interVpnLink : interVpnLinkList) {
329 if (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(vpnId)) {
330 return Optional.fromNullable(interVpnLink.getSecondEndpoint().getVpnUuid().getValue());
331 } else if (interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(vpnId)) {
332 return Optional.fromNullable(interVpnLink.getFirstEndpoint().getIpAddress().getValue());
336 return Optional.absent();
340 * Obtains the route-distinguisher for a given vpn-name
346 public static String getVpnRd(DataBroker broker, String vpnName) {
347 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
349 = getVpnInstanceToVpnIdIdentifier(vpnName);
350 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
351 .VpnInstance> vpnInstance
352 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
355 if(vpnInstance.isPresent()) {
356 rd = vpnInstance.get().getVrfId();
362 * Returns a boolean value which indicates if the endpoint's IP received as parameter belongs to any InterVpnLink.
365 * @param endpointIp IP to serch for.
368 public static boolean getInterVpnLinkByEndpointIp(DataBroker broker, String endpointIp) {
369 List<InterVpnLink> allInterVpnLinks = getAllInterVpnLinks(broker);
370 for (InterVpnLink interVpnLink : allInterVpnLinks) {
371 if (interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(endpointIp)
372 || interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(endpointIp)) {
379 public static int getUniqueId(IdManagerService idManager, String poolName, String idKey) {
380 AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
383 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
384 RpcResult<AllocateIdOutput> rpcResult = result.get();
385 if (rpcResult.isSuccessful()) {
386 return rpcResult.getResult().getIdValue().intValue();
388 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
390 } catch (InterruptedException | ExecutionException e) {
391 LOG.warn("Exception when getting Unique Id", e);
396 static final FutureCallback<Void> DEFAULT_CALLBACK =
397 new FutureCallback<Void>() {
399 public void onSuccess(Void result) {
400 LOG.debug("Success in Datastore operation");
404 public void onFailure(Throwable error) {
405 LOG.error("Error in Datastore operation", error);