All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI Maven / Gradle / Ivy

There is a newer version: 0.10.4
Show newest version
/*
 * Copyright (c) 2014, 2017 Cisco Systems, Inc. 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.sfc.provider.api;

import static org.opendaylight.sfc.provider.SfcProviderDebug.printTraceStart;
import static org.opendaylight.sfc.provider.SfcProviderDebug.printTraceStop;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffDataPlaneLocatorName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfpName;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwarders;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwardersState;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.SffDataPlaneLocator;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderKey;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.ConnectedSffDictionary;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.ServiceFunctionDictionary;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.state.ServiceFunctionForwarderState;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.state.ServiceFunctionForwarderStateKey;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.state.service.function.forwarder.state.SffServicePath;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.state.service.function.forwarder.state.SffServicePathBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.state.service.function.forwarder.state.SffServicePathKey;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class has the APIs to operate on the ServiceFunction datastore.
 *
 * 

* It is normally called from onDataChanged() through a executor service. We * need to use an executor service because we can not operate on a datastore * while on onDataChanged() context. * * @author Reinaldo Penno ([email protected]) * @author Konstantin Blagov ([email protected]) * @version 0.1 * @see org.opendaylight.sfc.provider.listeners.ServiceFunctionListener * @since 2014-06-30 */ public final class SfcProviderServiceForwarderAPI { private static final Logger LOG = LoggerFactory.getLogger(SfcProviderServiceForwarderAPI.class); private SfcProviderServiceForwarderAPI() { } /** * This method creates a SFF in the data store. * *

* * @param sff * SFF object * @return true if SFF was created, false otherwise */ public static boolean putServiceFunctionForwarder(ServiceFunctionForwarder sff) { boolean ret; printTraceStart(LOG); InstanceIdentifier sffEntryIID = InstanceIdentifier .builder(ServiceFunctionForwarders.class).child(ServiceFunctionForwarder.class, sff.key()).build(); ret = SfcDataStoreAPI.writePutTransactionAPI(sffEntryIID, sff, LogicalDatastoreType.CONFIGURATION); printTraceStop(LOG); return ret; } /** * This method searches for a data plane locator of a given name within a * SFF. * *

* * @param sffName * SFF name * @param sffLocatorName * SFF data plane locator name * @return SffDataPlaneLocator object or null if not found */ public static SffDataPlaneLocator readServiceFunctionForwarderDataPlaneLocator(SffName sffName, SffDataPlaneLocatorName sffLocatorName) { ServiceFunctionForwarder serviceFunctionForwarder = readServiceFunctionForwarder(sffName); if (serviceFunctionForwarder != null) { List sffDataPlaneLocatorList = serviceFunctionForwarder.getSffDataPlaneLocator(); for (SffDataPlaneLocator sffDataPlaneLocator : sffDataPlaneLocatorList) { if (sffDataPlaneLocator.getName().equals(sffLocatorName)) { return sffDataPlaneLocator; } } } else { LOG.error("{}: Failed to read SFF: {}", Thread.currentThread().getStackTrace()[1], sffName); } return null; } /** * This method reads a SFF from the datastore. * *

* * @param serviceFunctionForwarderName * SFF name * @return SF object or null if not found */ public static ServiceFunctionForwarder readServiceFunctionForwarder(SffName serviceFunctionForwarderName) { printTraceStart(LOG); ServiceFunctionForwarder sff; InstanceIdentifier sffIID; ServiceFunctionForwarderKey serviceFunctionForwarderKey = new ServiceFunctionForwarderKey(serviceFunctionForwarderName); sffIID = InstanceIdentifier.builder(ServiceFunctionForwarders.class) .child(ServiceFunctionForwarder.class, serviceFunctionForwarderKey).build(); sff = SfcDataStoreAPI.readTransactionAPI(sffIID, LogicalDatastoreType.CONFIGURATION); printTraceStop(LOG); return sff; } /** * This method deletes a SFF from the datastore. * *

* * @param serviceFunctionForwarderName * SFF name * @return true if SF was deleted, false otherwise */ public static boolean deleteServiceFunctionForwarder(SffName serviceFunctionForwarderName) { boolean ret = false; printTraceStart(LOG); ServiceFunctionForwarderKey serviceFunctionForwarderKey = new ServiceFunctionForwarderKey(serviceFunctionForwarderName); InstanceIdentifier sffEntryIID = InstanceIdentifier.builder(ServiceFunctionForwarders.class) .child(ServiceFunctionForwarder.class, serviceFunctionForwarderKey).build(); if (SfcDataStoreAPI.deleteTransactionAPI(sffEntryIID, LogicalDatastoreType.CONFIGURATION)) { ret = true; } else { LOG.error("Could not delete SFF: {}", serviceFunctionForwarderName); } printTraceStop(LOG); return ret; } /** * Read all Service Function Forwarders devices. * *

* * @return ServiceFunctionForwarders object */ public static ServiceFunctionForwarders readAllServiceFunctionForwarders() { ServiceFunctionForwarders sffs; printTraceStart(LOG); InstanceIdentifier sffsIID = InstanceIdentifier.builder(ServiceFunctionForwarders.class).build(); sffs = SfcDataStoreAPI.readTransactionAPI(sffsIID, LogicalDatastoreType.CONFIGURATION); printTraceStop(LOG); return sffs; } /** * We add the path name to the operational store of each SFF. * *

* * @param renderedServicePath * RSP Object * @return Nothing. */ public static boolean addPathToServiceForwarderState(RenderedServicePath renderedServicePath) { printTraceStart(LOG); boolean ret = true; // TODO another example of strings being used to interchange types. Note // the constructor of // a new SfpName. See prior TODO on RPC SffServicePathKey sffServicePathKey = new SffServicePathKey(new SfpName(renderedServicePath.getName().getValue())); SffServicePathBuilder sffServicePathBuilder = new SffServicePathBuilder(); sffServicePathBuilder.withKey(sffServicePathKey); sffServicePathBuilder.setName(new SfpName(renderedServicePath.getName().getValue())); List renderedServicePathHopList = renderedServicePath.getRenderedServicePathHop(); for (RenderedServicePathHop renderedServicePathHop : renderedServicePathHopList) { ServiceFunctionForwarderStateKey serviceFunctionForwarderStateKey = new ServiceFunctionForwarderStateKey(renderedServicePathHop.getServiceFunctionForwarder()); InstanceIdentifier sfStateIID = InstanceIdentifier.builder(ServiceFunctionForwardersState.class) .child(ServiceFunctionForwarderState.class, serviceFunctionForwarderStateKey) .child(SffServicePath.class, sffServicePathKey).build(); if (!SfcDataStoreAPI.writePutTransactionAPI(sfStateIID, sffServicePathBuilder.build(), LogicalDatastoreType.OPERATIONAL)) { ret = false; LOG.error("Failed to add path {} to SFF {} state.", renderedServicePath.getName(), renderedServicePathHop.getServiceFunctionForwarder()); } } printTraceStop(LOG); return ret; } /** * When a SFF is deleted we need to delete all SFPs from the associated SFF * operational state. * *

* * @param serviceFunctionPath * SFP object * @return true if all paths were deleted, false otherwise. */ public static boolean deletePathFromServiceForwarderState(ServiceFunctionPath serviceFunctionPath) { printTraceStart(LOG); boolean ret = true; // TODO Bug 4495 - RPCs hiding heuristics using Strings RspName rspName = new RspName(serviceFunctionPath.getName().getValue()); RenderedServicePath renderedServicePath = SfcProviderRenderedPathAPI .readRenderedServicePath(new RspName(serviceFunctionPath.getName().getValue())); if (renderedServicePath != null) { Set sffNameSet = new HashSet<>(); List renderedServicePathHopList = renderedServicePath.getRenderedServicePathHop(); for (RenderedServicePathHop renderedServicePathHop : renderedServicePathHopList) { SffName sffName = renderedServicePathHop.getServiceFunctionForwarder(); if (sffNameSet.add(sffName)) { // TODO Bug 4495 - RPCs hiding heuristics using Strings - SffServicePathKey sffServicePathKey = new SffServicePathKey(new SfpName(rspName.getValue())); ServiceFunctionForwarderStateKey serviceFunctionForwarderStateKey = new ServiceFunctionForwarderStateKey(sffName); InstanceIdentifier sfStateIID = InstanceIdentifier.builder(ServiceFunctionForwardersState.class) .child(ServiceFunctionForwarderState.class, serviceFunctionForwarderStateKey) .child(SffServicePath.class, sffServicePathKey).build(); if (SfcDataStoreAPI.deleteTransactionAPI(sfStateIID, LogicalDatastoreType.OPERATIONAL)) { ret = true; } else { ret = false; LOG.error("Could not delete Service Path {} from SFF {}", rspName, sffName); } List sffServicePathList = readSffState(sffName); if (sffServicePathList != null && sffServicePathList.isEmpty() && !deleteServiceFunctionForwarderState(sffName)) { ret = false; } } } } else { LOG.error("{}: Rendered Service Path {} does not exist", Thread.currentThread().getStackTrace()[1], serviceFunctionPath.getName()); } printTraceStop(LOG); return ret; } /** * Delete the given list of service paths from the SFF operational state. * *

* * @param renderedServicePaths * String List of Service Path names * @return True if paths were deleted, false otherwise */ public static boolean deletePathFromServiceForwarderState(List renderedServicePaths) { printTraceStart(LOG); boolean ret = false; for (RspName rspName : renderedServicePaths) { if (SfcProviderServiceForwarderAPI.deletePathFromServiceForwarderState(rspName)) { ret = true; } else { LOG.debug("RSP {} already deleted by another thread or client", rspName); ret = true; } } printTraceStop(LOG); return ret; } /** * When a SFF is deleted we need to delete all SFPs from the associated SFF. * operational state * *

* * @param rspName * SFP object * @return true if all path was deleted, false otherwise. */ public static boolean deletePathFromServiceForwarderState(RspName rspName) { printTraceStart(LOG); boolean ret = true; RenderedServicePath renderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName); if (renderedServicePath != null) { Set sffNameSet = new HashSet<>(); List renderedServicePathHopList = renderedServicePath.getRenderedServicePathHop(); for (RenderedServicePathHop renderedServicePathHop : renderedServicePathHopList) { SffName sffname = renderedServicePathHop.getServiceFunctionForwarder(); if (sffNameSet.add(sffname)) { // TODO Bug 4495 - RPCs hiding heuristics using Strings - SffServicePathKey sffServicePathKey = new SffServicePathKey(new SfpName(rspName.getValue())); ServiceFunctionForwarderStateKey serviceFunctionForwarderStateKey = new ServiceFunctionForwarderStateKey(sffname); InstanceIdentifier sfStateIID = InstanceIdentifier.builder(ServiceFunctionForwardersState.class) .child(ServiceFunctionForwarderState.class, serviceFunctionForwarderStateKey) .child(SffServicePath.class, sffServicePathKey).build(); if (SfcDataStoreAPI.deleteTransactionAPI(sfStateIID, LogicalDatastoreType.OPERATIONAL)) { ret = true; } else { ret = false; LOG.error("Could not delete Service Path {} from SFF {}", rspName, sffname); } List sffServicePathList = readSffState(sffname); if (sffServicePathList != null && sffServicePathList.isEmpty() && !deleteServiceFunctionForwarderState(sffname)) { ret = false; } } } } else { LOG.error("{}: Rendered Service Path {} does not exist", Thread.currentThread().getStackTrace()[1], rspName); } printTraceStop(LOG); return ret; } /** * This method deletes the operational state for a service function. * *

* * @param sffName * SFF name * @return A ServiceFunctionState object that is a list of all paths using * this service function, null otherwise */ public static boolean deleteServiceFunctionForwarderState(SffName sffName) { printTraceStart(LOG); boolean ret = false; ServiceFunctionForwarderStateKey serviceFunctionForwarderStateKey = new ServiceFunctionForwarderStateKey(sffName); InstanceIdentifier sffStateIID = InstanceIdentifier.builder(ServiceFunctionForwardersState.class) .child(ServiceFunctionForwarderState.class, serviceFunctionForwarderStateKey).build(); if (SfcDataStoreAPI.deleteTransactionAPI(sffStateIID, LogicalDatastoreType.OPERATIONAL)) { ret = true; } else { LOG.error("{}: Could not delete operational state for SFF: {}", Thread.currentThread().getStackTrace()[1], sffName); } return ret; } /** * Returns the list of SFPs anchored by a SFF. * *

* * @param sffName * SFF name * @return List of SFF service paths or null if no SFF state info exists */ public static List readSffState(SffName sffName) { printTraceStart(LOG); List ret = null; ServiceFunctionForwarderStateKey serviceFunctionForwarderStateKey = new ServiceFunctionForwarderStateKey(sffName); InstanceIdentifier sfStateIID = InstanceIdentifier.builder(ServiceFunctionForwardersState.class) .child(ServiceFunctionForwarderState.class, serviceFunctionForwarderStateKey).build(); ServiceFunctionForwarderState sffStateDataObject; sffStateDataObject = SfcDataStoreAPI.readTransactionAPI(sfStateIID, LogicalDatastoreType.OPERATIONAL); // Read the list of Service Function Path anchored by this SFF if (sffStateDataObject != null) { ret = sffStateDataObject.getSffServicePath() != null ? sffStateDataObject.getSffServicePath() : Collections.emptyList(); } else { LOG.warn("Service Function Forwarder {} has no operational state", sffName); } printTraceStop(LOG); return ret; } /** * Returns the list of {@link RspName} anchored by a SFF. * * @param sffName * the SFF name. * @return the list of {@link RspName}. */ public static List readRspNamesFromSffState(SffName sffName) { return Optional.ofNullable(SfcProviderServiceForwarderAPI.readSffState(sffName)).orElse(Collections.emptyList()) .stream().map(SffServicePath::getName).map(SfpName::getValue).map(RspName::new) .collect(Collectors.toList()); } /** * Return a list of SffDataPlaneLocator that are not used by any SF, which * is determined by looking at the Sff.SfDictionary.SffSfDpl.SffDpl. This is * useful when there are multiple SFF DPLs, this returns the DPLs that are * not used by SFs. For example, in the case of Vxgpe+NSH between the SFFs, * and Eth+NSH to the SFs, there will be a Eth+NSH Dpl per SF, and just 1 * Vxgpe+NSH DPL for the SFF-SFF, which will be returned by this method. * * @param sff * - The SFF to process * @return List of SffDataPlaneLocator not used by any SF */ public static List getNonSfDataPlaneLocators(ServiceFunctionForwarder sff) { List nonSfDpls = new ArrayList<>(); for (SffDataPlaneLocator sffDpl : sff.getSffDataPlaneLocator()) { boolean dplInSf = false; if (sff.getServiceFunctionDictionary() == null) { LOG.error("getNonSfDataPlaneLocators NULL getServiceFunctionDictionary"); continue; } for (ServiceFunctionDictionary sffDict : sff.getServiceFunctionDictionary()) { if (sffDict.getSffSfDataPlaneLocator() == null || sffDict.getSffSfDataPlaneLocator().getSffDplName() == null) { LOG.error("getNonSfDataPlaneLocators NULL getSffSfDataPlaneLocator or SffDplName"); continue; } if (sffDpl.getName().toString().equals(sffDict.getSffSfDataPlaneLocator().getSffDplName().toString())) { dplInSf = true; break; } } if (!dplInSf) { LOG.debug("getNonSfDataPlaneLocators found NonSf DPL [{}] from SFF [{}]", sffDpl.getName(), sff.getName()); nonSfDpls.add(sffDpl); } } return nonSfDpls; } public static ConnectedSffDictionary getSffSffConnectedDictionary(SffName sffName, SffName dstSffName) { ConnectedSffDictionary foundSffDict = null; ServiceFunctionForwarder sff = readServiceFunctionForwarder(sffName); if (sff == null || sff.getSffDataPlaneLocator() == null) { return null; } List sffDictList = sff.getConnectedSffDictionary(); if (sffDictList != null) { for (ConnectedSffDictionary sffDict : sffDictList) { if (sffDict.getName().getValue().equals(dstSffName.getValue())) { foundSffDict = sffDict; break; } } } return foundSffDict; } public static SffName getSffName(String nodeName) { ServiceFunctionForwarders sffs = readAllServiceFunctionForwarders(); for (ServiceFunctionForwarder sff : sffs.getServiceFunctionForwarder()) { if (nodeName.equals(sff.getServiceNode().getValue())) { return sff.getName(); } } return null; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy