/* * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.vpnservice; import java.math.BigInteger; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.List; import com.google.common.base.Optional; import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.vpnservice.mdsalutil.NwConstants; import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces; import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance; import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances; import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey; import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface; import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey; import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.*; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIdsKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.Vpn; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.VpnKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.binding.DataObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class VpnUtil { private static final Logger LOG = LoggerFactory.getLogger(VpnUtil.class); private static final int DEFAULT_PREFIX_LENGTH = 32; private static final String PREFIX_SEPARATOR = "/"; static InstanceIdentifier getVpnInterfaceIdentifier(String vpnInterfaceName) { return InstanceIdentifier.builder(VpnInterfaces.class) .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build(); } static InstanceIdentifier getVpnInstanceIdentifier(String vpnName) { return InstanceIdentifier.builder(VpnInstances.class) .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build(); } static VpnInterface getVpnInterface(String intfName, String vpnName, Adjacencies aug) { return new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(intfName)).setVpnInstanceName(vpnName) .addAugmentation(Adjacencies.class, aug) .build(); } static InstanceIdentifier getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) { return InstanceIdentifier.builder(PrefixToInterface.class) .child(VpnIds.class, new VpnIdsKey(vpnId)).child(Prefixes.class, new PrefixesKey(ipPrefix)).build(); } static Prefixes getPrefixToInterface(BigInteger dpId, String vpnInterfaceName, String ipPrefix) { return new PrefixesBuilder().setDpnId(dpId).setVpnInterfaceName( vpnInterfaceName).setIpAddress(ipPrefix).build(); } static InstanceIdentifier getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) { return InstanceIdentifier.builder(VpnToExtraroute.class) .child(Vpn.class, new VpnKey(vrfId)).child(Extraroute.class, new ExtrarouteKey(ipPrefix)).build(); } static Extraroute getVpnToExtraroute(String ipPrefix, String nextHop) { return new ExtrarouteBuilder().setPrefix(ipPrefix).setNexthopIp(nextHop).build(); } static Adjacencies getVpnInterfaceAugmentation(List nextHops) { return new AdjacenciesBuilder().setAdjacency(nextHops).build(); } public static InstanceIdentifier getPoolId(String poolName){ InstanceIdentifier.InstanceIdentifierBuilder idBuilder = InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName)); InstanceIdentifier id = idBuilder.build(); return id; } static InstanceIdentifier getVpnInterfacesIdentifier() { return InstanceIdentifier.builder(VpnInterfaces.class).build(); } static InstanceIdentifier getInterfaceIdentifier(String interfaceName) { return InstanceIdentifier.builder(Interfaces.class) .child(Interface.class, new InterfaceKey(interfaceName)).build(); } static InstanceIdentifier getVpnToDpnListIdentifier(String rd, BigInteger dpnId) { return InstanceIdentifier.builder(VpnInstanceOpData.class) .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)) .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build(); } public static BigInteger getCookieArpFlow(int interfaceTag) { return VpnConstants.COOKIE_L3_BASE.add(new BigInteger("0110000", 16)).add( BigInteger.valueOf(interfaceTag)); } public static String getFlowRef(BigInteger dpnId, short tableId, int ethType, int lPortTag, int arpType) { return new StringBuffer().append(VpnConstants.FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR) .append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(ethType).append(lPortTag) .append(NwConstants.FLOWID_SEPARATOR).append(arpType).toString(); } public static int getUniqueId(IdManagerService idManager, String poolName,String idKey) { AllocateIdInput getIdInput = new AllocateIdInputBuilder() .setPoolName(poolName) .setIdKey(idKey).build(); try { Future> result = idManager.allocateId(getIdInput); RpcResult rpcResult = result.get(); if(rpcResult.isSuccessful()) { return rpcResult.getResult().getIdValue().intValue(); } else { LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors()); } } catch (InterruptedException | ExecutionException e) { LOG.warn("Exception when getting Unique Id",e); } return 0; } public static void releaseId(IdManagerService idManager, String poolName, String idKey) { ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build(); try { Future> result = idManager.releaseId(idInput); RpcResult rpcResult = result.get(); if(!rpcResult.isSuccessful()) { LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors()); } } catch (InterruptedException | ExecutionException e) { LOG.warn("Exception when getting Unique Id for key {}", idKey, e); } } public static String getNextHopLabelKey(String rd, String prefix){ String key = rd + VpnConstants.SEPARATOR + prefix; return key; } public static long getVpnId(DataBroker broker, String vpnName) { InstanceIdentifier id = getVpnInstanceToVpnIdIdentifier(vpnName); Optional vpnInstance = read(broker, LogicalDatastoreType.CONFIGURATION, id); long vpnId = VpnConstants.INVALID_ID; if(vpnInstance.isPresent()) { vpnId = vpnInstance.get().getVpnId(); } return vpnId; } public static String getVpnRd(DataBroker broker, String vpnName) { InstanceIdentifier id = getVpnInstanceToVpnIdIdentifier(vpnName); Optional vpnInstance = read(broker, LogicalDatastoreType.CONFIGURATION, id); String rd = null; if(vpnInstance.isPresent()) { rd = vpnInstance.get().getVrfId(); } return rd; } static org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance getVpnInstanceToVpnId(String vpnName, long vpnId, String rd) { return new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceBuilder() .setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).build(); } static InstanceIdentifier getVpnInstanceToVpnIdIdentifier(String vpnName) { return InstanceIdentifier.builder(VpnInstanceToVpnId.class) .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build(); } static InstanceIdentifier getVpnInstanceOpDataIdentifier(String rd) { return InstanceIdentifier.builder(VpnInstanceOpData.class) .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build(); } static VpnInstanceOpDataEntry getVpnInstanceOpDataBuilder(String rd, long vpnId) { return new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).build(); } static VpnInstanceOpDataEntry updateIntfCntInVpnInstOpData(Long count, String vrfId) { return new VpnInstanceOpDataEntryBuilder().setVpnInterfaceCount(count).setVrfId(vrfId).build(); } static VpnInstanceOpDataEntry getVpnInstanceOpData(DataBroker broker, String rd) { InstanceIdentifier id = VpnUtil.getVpnInstanceOpDataIdentifier(rd); Optional vpnInstanceOpData = read(broker, LogicalDatastoreType.OPERATIONAL, id); if(vpnInstanceOpData.isPresent()) { return vpnInstanceOpData.get(); } return null; } static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) { InstanceIdentifier interfaceId = getVpnInterfaceIdentifier(interfaceName); Optional configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId); if (configuredVpnInterface.isPresent()) { return configuredVpnInterface.get(); } return null; } static VpnInterface getOperationalVpnInterface(DataBroker broker, String interfaceName) { InstanceIdentifier interfaceId = getVpnInterfaceIdentifier(interfaceName); Optional operationalVpnInterface = read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId); if (operationalVpnInterface.isPresent()) { return operationalVpnInterface.get(); } return null; } static boolean isVpnInterfaceConfigured(DataBroker broker, String interfaceName) { InstanceIdentifier interfaceId = getVpnInterfaceIdentifier(interfaceName); Optional configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId); if (configuredVpnInterface.isPresent()) { return true; } return false; } static String getIpPrefix(String prefix) { String prefixValues[] = prefix.split("/"); if (prefixValues.length == 1) { prefix = prefix + PREFIX_SEPARATOR + DEFAULT_PREFIX_LENGTH ; } return prefix; } static final FutureCallback DEFAULT_CALLBACK = new FutureCallback() { public void onSuccess(Void result) { LOG.debug("Success in Datastore operation"); } public void onFailure(Throwable error) { LOG.error("Error in Datastore operation", error); }; }; public static Optional read(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path) { ReadOnlyTransaction tx = broker.newReadOnlyTransaction(); Optional result = Optional.absent(); try { result = tx.read(datastoreType, path).get(); } catch (Exception e) { throw new RuntimeException(e); } return result; } static void asyncUpdate(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path, T data, FutureCallback callback) { WriteTransaction tx = broker.newWriteOnlyTransaction(); tx.merge(datastoreType, path, data, true); Futures.addCallback(tx.submit(), callback); } static void asyncWrite(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path, T data, FutureCallback callback) { WriteTransaction tx = broker.newWriteOnlyTransaction(); tx.put(datastoreType, path, data, true); Futures.addCallback(tx.submit(), callback); } static void delete(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path, FutureCallback callback) { WriteTransaction tx = broker.newWriteOnlyTransaction(); tx.delete(datastoreType, path); Futures.addCallback(tx.submit(), callback); } public static void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path, T data) { WriteTransaction tx = broker.newWriteOnlyTransaction(); tx.put(datastoreType, path, data, true); CheckedFuture futures = tx.submit(); try { futures.get(); } catch (InterruptedException | ExecutionException e) { LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data); throw new RuntimeException(e.getMessage()); } } public static void syncUpdate(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path, T data) { WriteTransaction tx = broker.newWriteOnlyTransaction(); tx.merge(datastoreType, path, data, true); CheckedFuture futures = tx.submit(); try { futures.get(); } catch (InterruptedException | ExecutionException e) { LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data); throw new RuntimeException(e.getMessage()); } } }