Initial commit of Path Computation Server.
This is the 3/3 Patch Set to provide Path Computation Element (PCE)
conform to RFC5440. This integrates the Graph model and Algorithms
features. Graph is fulfilled from BGP-LinkState if available otherwise
a graph must be provided.
Details information about how to use the PCE server will be provided
in docs/pcep/pcep-user-guide-pce-server.rst
JIRA: BGPCEP-858
Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
Change-Id: Ic0552b4c7ad856fe7a7cca214bbaf81f659d876c
<groupId>${project.groupId}</groupId>
<artifactId>topology-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>graph-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>odl-uint24</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>concepts</artifactId>
@GuardedBy("this")
@VisibleForTesting
protected int listenerScheduledRestartEnforceCounter = 0;
+ protected boolean networkTopologyTransaction = true;
protected AbstractTopologyBuilder(final DataBroker dataProvider, final RibReference locRibReference,
final TopologyId topologyId, final TopologyTypes types, final Class<? extends AddressFamily> afi,
@Override
@SuppressWarnings("checkstyle:IllegalCatch")
public synchronized void onDataTreeChanged(final Collection<DataTreeModification<T>> changes) {
- if (this.closed.get()) {
- LOG.trace("Transaction chain was already closed, skipping update.");
- return;
- }
- // check if the transaction chain needed to be restarted due to a previous error
- if (restartTransactionChainOnDemand()) {
- LOG.debug("The data change {} is disregarded due to restart of listener {}", changes, this);
- return;
- }
- final ReadWriteTransaction trans = this.chain.newReadWriteTransaction();
- LOG.trace("Received data change {} event with transaction {}", changes, trans.getIdentifier());
- final AtomicBoolean transactionInError = new AtomicBoolean(false);
- for (final DataTreeModification<T> change : changes) {
- try {
- routeChanged(change, trans);
- } catch (final RuntimeException exc) {
- LOG.warn("Data change {} (transaction {}) was not completely propagated to listener {}", change,
- trans.getIdentifier(), this, exc);
- // trans.cancel() is not supported by PingPongTransactionChain, so we just skip the problematic change
- // trans.commit() must be called first to unlock the current transaction chain, to make the chain
- // closable so we cannot exit the #onDataTreeChanged() yet
- transactionInError.set(true);
- break;
+ if (networkTopologyTransaction) {
+ if (this.closed.get()) {
+ LOG.trace("Transaction chain was already closed, skipping update.");
+ return;
}
- }
- trans.commit().addCallback(new FutureCallback<CommitInfo>() {
- @Override
- public void onSuccess(final CommitInfo result) {
- // as we are enforcing trans.commit(), in some cases the transaction execution actually could be
- // successfully even when an exception is captured, thus #onTransactionChainFailed() never get invoked.
- // Though the transaction chain remains usable,
- // the data loss will not be able to be recovered. Thus we schedule a listener restart here
- if (transactionInError.get()) {
- LOG.warn("Transaction {} committed successfully while exception captured. Rescheduling a restart"
- + " of listener {}", trans
- .getIdentifier(), AbstractTopologyBuilder.this);
- scheduleListenerRestart();
- } else {
- LOG.trace("Transaction {} committed successfully", trans.getIdentifier());
+ // check if the transaction chain needed to be restarted due to a previous error
+ if (restartTransactionChainOnDemand()) {
+ LOG.debug("The data change {} is disregarded due to restart of listener {}", changes, this);
+ return;
+ }
+ final ReadWriteTransaction trans = this.chain.newReadWriteTransaction();
+ LOG.trace("Received data change {} event with transaction {}", changes, trans.getIdentifier());
+ final AtomicBoolean transactionInError = new AtomicBoolean(false);
+ for (final DataTreeModification<T> change : changes) {
+ try {
+ routeChanged(change, trans);
+ } catch (final RuntimeException exc) {
+ LOG.warn("Data change {} (transaction {}) was not completely propagated to listener {}", change,
+ trans.getIdentifier(), this, exc);
+ // trans.cancel() is not supported by PingPongTransactionChain, so we just skip the problematic
+ // change.
+ // trans.commit() must be called first to unlock the current transaction chain, to make the chain
+ // closable so we cannot exit the #onDataTreeChanged() yet
+ transactionInError.set(true);
+ break;
}
}
+ trans.commit().addCallback(new FutureCallback<CommitInfo>() {
+ @Override
+ public void onSuccess(final CommitInfo result) {
+ // as we are enforcing trans.commit(), in some cases the transaction execution actually could be
+ // successfully even when an exception is captured, thus #onTransactionChainFailed() never get
+ // invoked. Though the transaction chain remains usable,
+ // the data loss will not be able to be recovered. Thus we schedule a listener restart here
+ if (transactionInError.get()) {
+ LOG.warn("Transaction {} committed successfully while exception captured. Rescheduling a"
+ + " restart of listener {}", trans
+ .getIdentifier(), AbstractTopologyBuilder.this);
+ scheduleListenerRestart();
+ } else {
+ LOG.trace("Transaction {} committed successfully", trans.getIdentifier());
+ }
+ }
- @Override
- public void onFailure(final Throwable throwable) {
- // we do nothing but print out the log. Transaction chain restart will be done in
- // #onTransactionChainFailed()
- LOG.error("Failed to propagate change (transaction {}) by listener {}", trans.getIdentifier(),
- AbstractTopologyBuilder.this, throwable);
+ @Override
+ public void onFailure(final Throwable throwable) {
+ // we do nothing but print out the log. Transaction chain restart will be done in
+ // #onTransactionChainFailed()
+ LOG.error("Failed to propagate change (transaction {}) by listener {}", trans.getIdentifier(),
+ AbstractTopologyBuilder.this, throwable);
+ }
+ }, MoreExecutors.directExecutor());
+ } else {
+ for (final DataTreeModification<T> change : changes) {
+ routeChanged(change, null);
}
- }, MoreExecutors.directExecutor());
+ }
}
@VisibleForTesting
--- /dev/null
+/*
+ * Copyright (c) 2020 Orange. 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.bgpcep.bgp.topology.provider;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import java.math.BigDecimal;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.graph.ConnectedGraph;
+import org.opendaylight.graph.ConnectedGraphProvider;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
+import org.opendaylight.protocol.bgp.rib.RibReference;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.LinkstateAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.LinkstateSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.bgp.rib.rib.loc.rib.tables.routes.LinkstateRoutesCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.ObjectType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.SrAdjIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.LinkCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.NodeCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.PrefixCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.LinkDescriptors;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.LinkStateAttribute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.LinkAttributesCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.NodeAttributesCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.PrefixAttributesCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.link.attributes._case.LinkAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.node.attributes._case.NodeAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.LinkstateRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRoute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.linkstate.route.Attributes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.CRouterIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.c.router.identifier.IsisNodeCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.c.router.identifier.OspfNodeCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.adj.flags.flags.isis.adj.flags._case.IsisAdjFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.adj.flags.flags.ospf.adj.flags._case.OspfAdjFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.prefix.sid.tlv.flags.IsisPrefixFlagsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.LocalLabelCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.SidCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.DecimalBandwidth;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.Delay;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.Loss;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.Vertex.VertexType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.edge.EdgeAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.edge.EdgeAttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.edge.attributes.MinMaxDelay;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.edge.attributes.MinMaxDelayBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.edge.attributes.UnreservedBandwidth;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.edge.attributes.UnreservedBandwidthBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.edge.attributes.UnreservedBandwidthKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.Graph.DomainScope;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.Edge;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.EdgeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.EdgeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.PrefixBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.Vertex;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.VertexBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.VertexKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.vertex.SrgbBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.topology.types.rev160524.TopologyTypes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.topology.types.rev160524.TopologyTypes1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.topology.types.rev160524.bgp.linkstate.topology.type.BgpLinkstateTopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.SrlgId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypesBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This Class build the Traffic Engineering Database as a Connected Graph
+ * suitable to be used latter by Path Computation algorithms to compute end to
+ * end path.
+ *
+ * @author Olivier Dugeon
+ * @author Philippe Niger
+ *
+ */
+
+public class LinkstateGraphBuilder extends AbstractTopologyBuilder<LinkstateRoute> {
+ private static final TopologyTypes LINKSTATE_TOPOLOGY_TYPE = new TopologyTypesBuilder().addAugmentation(
+ TopologyTypes1.class,
+ new TopologyTypes1Builder().setBgpLinkstateTopology(new BgpLinkstateTopologyBuilder().build()).build())
+ .build();
+
+ private static final String UNHANDLED_OBJECT_CLASS = "Unhandled object class {}";
+
+ private static final Logger LOG = LoggerFactory.getLogger(LinkstateGraphBuilder.class);
+
+ private ConnectedGraphProvider graphProvider;
+ private ConnectedGraph cgraph;
+
+ public LinkstateGraphBuilder(final DataBroker dataProvider, final RibReference locRibReference,
+ final TopologyId topologyId, ConnectedGraphProvider provider) {
+ super(dataProvider, locRibReference, topologyId, LINKSTATE_TOPOLOGY_TYPE, LinkstateAddressFamily.class,
+ LinkstateSubsequentAddressFamily.class);
+ this.graphProvider = requireNonNull(provider);
+ this.cgraph = provider.createConnectedGraph("ted://" + topologyId.getValue(),
+ DomainScope.IntraDomain);
+ /* LinkStateGraphBuilder doesn't write information in the Network Topology tree of the Data Store.
+ * This is performed by ConnectedGraphProvider which write element in Graph tree of the Data Store */
+ this.networkTopologyTransaction = false;
+ LOG.info("Started Traffic Engineering Graph Builder");
+ }
+
+ @VisibleForTesting
+ LinkstateGraphBuilder(final DataBroker dataProvider, final RibReference locRibReference,
+ final TopologyId topologyId, ConnectedGraphProvider provider, final long listenerResetLimitInMillsec,
+ final int listenerResetEnforceCounter) {
+ super(dataProvider, locRibReference, topologyId, LINKSTATE_TOPOLOGY_TYPE, LinkstateAddressFamily.class,
+ LinkstateSubsequentAddressFamily.class, listenerResetLimitInMillsec, listenerResetEnforceCounter);
+ this.graphProvider = requireNonNull(provider);
+ this.cgraph = provider.createConnectedGraph("ted://" + topologyId.getValue(),
+ DomainScope.IntraDomain);
+ /* LinkStateGraphBuilder doesn't write information in the Network Topology tree of the Data Store.
+ * This is performed by ConnectedGraphProvider which write element in Graph tree of the Data Store */
+ this.networkTopologyTransaction = false;
+ LOG.info("Started Traffic Engineering Graph Builder");
+ }
+
+ @Override
+ protected void createObject(final ReadWriteTransaction trans, final InstanceIdentifier<LinkstateRoute> id,
+ final LinkstateRoute value) {
+ final ObjectType t = value.getObjectType();
+ Preconditions.checkArgument(t != null, "Route %s value %s has null object type", id, value);
+
+ if (t instanceof LinkCase) {
+ createEdge(value, (LinkCase) t, value.getAttributes());
+ } else if (t instanceof NodeCase) {
+ createVertex(value, (NodeCase) t, value.getAttributes());
+ } else if (t instanceof PrefixCase) {
+ createPrefix(value, (PrefixCase) t, value.getAttributes());
+ } else {
+ LOG.debug(UNHANDLED_OBJECT_CLASS, t.implementedInterface());
+ }
+ }
+
+ /**
+ * Verify that mandatory information (Local & Remote Node and Link
+ * descriptors) are present in the link.
+ *
+ * @param linkCase The Link part of the Linkstate route
+ *
+ * @return True if all information are present, false otherwise
+ */
+ private boolean checkLinkState(final LinkCase linkCase) {
+ if (linkCase.getLocalNodeDescriptors() == null || linkCase.getRemoteNodeDescriptors() == null) {
+ LOG.warn("Missing Local or Remote Node descriptor in link {}, skipping it", linkCase);
+ return false;
+ }
+ if (linkCase.getLinkDescriptors() == null) {
+ LOG.warn("Missing Link descriptor in link {}, skipping it", linkCase);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Get Link attributes from the Link State route.
+ *
+ * @param attributes Link State Route Attributes
+ *
+ * @return Link Attributes
+ */
+ private LinkAttributes getLinkAttributes(final Attributes attributes) {
+ final LinkAttributes la;
+ final Attributes1 attr = attributes.augmentation(Attributes1.class);
+ if (attr != null) {
+ final LinkStateAttribute attrType = attr.getLinkStateAttribute();
+ if (attrType != null) {
+ la = ((LinkAttributesCase) attrType).getLinkAttributes();
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ return la;
+ }
+
+ /**
+ * Determine the Source Edge Key from the link descriptor.
+ * There is several case: IPv4, IPv6 address or Unnumbered Interface.
+ *
+ * @param linkCase The Link part of the Linkstate route
+ *
+ * @return Unique key
+ */
+ private Uint64 getEdgeId(LinkCase linkCase) {
+ long key = 0;
+ if (linkCase.getLinkDescriptors().getIpv4InterfaceAddress() != null) {
+ key = ipv4ToKey(linkCase.getLinkDescriptors().getIpv4InterfaceAddress().getValue());
+ }
+ if (linkCase.getLinkDescriptors().getIpv6InterfaceAddress() != null) {
+ key = ipv6ToKey(linkCase.getLinkDescriptors().getIpv6InterfaceAddress().getValue());
+ }
+ if (linkCase.getLinkDescriptors().getLinkLocalIdentifier() != null) {
+ key = linkCase.getLinkDescriptors().getLinkLocalIdentifier().longValue();
+ }
+ return Uint64.valueOf(key);
+ }
+
+ /**
+ * Create new Connected Edge in the Connected Graph.
+ *
+ * @param value The complete Linkstate route information
+ * @param linkCase The Link part of the Linkstate route
+ * @param attributes The Link attributes
+ *
+ */
+ private void createEdge(final LinkstateRoute value, final LinkCase linkCase, final Attributes attributes) {
+ Preconditions.checkArgument(checkLinkState(linkCase), "Missing mandatory information in link {}", linkCase);
+
+ final LinkAttributes la = getLinkAttributes(attributes);
+ if (la == null) {
+ LOG.warn("Missing attributes in link {} route {}, skipping it", linkCase, value);
+ return;
+ }
+
+ /* Get Source and Destination Vertex from the graph */
+ Uint64 srcId = getVertexId(linkCase.getLocalNodeDescriptors().getCRouterIdentifier());
+ Uint64 dstId = getVertexId(linkCase.getRemoteNodeDescriptors().getCRouterIdentifier());
+ if (srcId == Uint64.ZERO || dstId == Uint64.ZERO) {
+ LOG.warn("Unable to get the Source or Destination Vertex Identifier from link {}, skipping it", linkCase);
+ return;
+ }
+
+ /* Get Source and Destination Key for the corresponding Edge */
+ Uint64 edgeId = getEdgeId(linkCase);
+ if (edgeId == Uint64.ZERO) {
+ LOG.warn("Unable to get the Edge Identifier from link {}, skipping it", linkCase);
+ return;
+ }
+
+ /* Add associated Edge */
+ Edge edge = new EdgeBuilder().setEdgeId(edgeId).setLocalVertexId(srcId).setRemoteVertexId(dstId)
+ .setName(srcId + " - " + dstId)
+ .setEdgeAttributes(createEdgeAttributes(la, linkCase.getLinkDescriptors())).build();
+
+ /*
+ * Add corresponding Prefix for the Local Address. Remote address will be added with the remote Edge */
+ PrefixBuilder prefBuilder = new PrefixBuilder().setVertexId(srcId);
+ if (edge.getEdgeAttributes().getLocalAddress().getIpv4Address() != null) {
+ prefBuilder.setPrefix(new IpPrefix(
+ new Ipv4Prefix(edge.getEdgeAttributes().getLocalAddress().getIpv4Address().getValue() + "/32")));
+ }
+ if (edge.getEdgeAttributes().getLocalAddress().getIpv6Address() != null) {
+ prefBuilder.setPrefix(new IpPrefix(
+ new Ipv6Prefix(edge.getEdgeAttributes().getLocalAddress().getIpv6Address().getValue() + "/128")));
+ }
+ Prefix prefix = prefBuilder.build();
+
+ /* Add the Edge in the Connected Graph */
+ LOG.info("Add Edge {} and associated Prefix {} in TED[{}]", edge.getName(), prefix.getPrefix(), cgraph);
+ cgraph.addEdge(edge);
+ cgraph.addPrefix(prefix);
+ }
+
+ /**
+ * Create Edge Attributes from Link attributes.
+ *
+ * @param la Linkstate Attributes
+ * @param linkDesc Linkstate Descriptors
+ *
+ * @return EdgeAttributes
+ */
+ private static final int MAX_PRIORITY = 8;
+
+ private EdgeAttributes createEdgeAttributes(LinkAttributes la, final LinkDescriptors linkDesc) {
+ EdgeAttributesBuilder builder = new EdgeAttributesBuilder();
+
+ if (linkDesc.getIpv4InterfaceAddress() != null) {
+ builder.setLocalAddress(new IpAddress(new Ipv4Address(linkDesc.getIpv4InterfaceAddress())));
+ }
+ if (linkDesc.getIpv6InterfaceAddress() != null) {
+ builder.setLocalAddress(new IpAddress(new Ipv6Address(linkDesc.getIpv6InterfaceAddress())));
+ }
+ if (linkDesc.getIpv4NeighborAddress() != null) {
+ builder.setRemoteAddress(new IpAddress(new Ipv4Address(linkDesc.getIpv4NeighborAddress())));
+ }
+ if (linkDesc.getIpv6NeighborAddress() != null) {
+ builder.setRemoteAddress(new IpAddress(new Ipv6Address(linkDesc.getIpv6NeighborAddress())));
+ }
+ if (linkDesc.getLinkLocalIdentifier() != null) {
+ builder.setLocalIdentifier(linkDesc.getLinkLocalIdentifier());
+ }
+ if (linkDesc.getLinkRemoteIdentifier() != null) {
+ builder.setRemoteIdentifier(linkDesc.getLinkRemoteIdentifier());
+ }
+ if (la.getMetric() != null) {
+ builder.setMetric(la.getMetric().getValue());
+ }
+ if (la.getTeMetric() != null) {
+ builder.setTeMetric(la.getTeMetric().getValue());
+ }
+ if (la.getMaxLinkBandwidth() != null) {
+ builder.setMaxLinkBandwidth(bandwithToDecimalBandwidth(la.getMaxLinkBandwidth()));
+ }
+ if (la.getMaxReservableBandwidth() != null) {
+ builder.setMaxResvLinkBandwidth(bandwithToDecimalBandwidth(la.getMaxReservableBandwidth()));
+ }
+ if (la.getUnreservedBandwidth() != null) {
+ int upperBound = Math.min(la.getUnreservedBandwidth().size(), MAX_PRIORITY);
+ final List<UnreservedBandwidth> unRsvBw = new ArrayList<>(upperBound);
+
+ for (final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120
+ .UnreservedBandwidth bandwidth : la.getUnreservedBandwidth()) {
+ unRsvBw.add(new UnreservedBandwidthBuilder()
+ .setBandwidth(bandwithToDecimalBandwidth(bandwidth.getBandwidth()))
+ .withKey(new UnreservedBandwidthKey(bandwidth.getPriority())).build());
+ }
+ builder.setUnreservedBandwidth(unRsvBw);
+ }
+ if (la.getAdminGroup() != null) {
+ builder.setAdminGroup(la.getAdminGroup().getValue());
+ }
+ if (la.getLinkDelay() != null) {
+ builder.setDelay(new Delay(la.getLinkDelay().getValue()));
+ }
+ if (la.getLinkMinMaxDelay() != null && la.getLinkMinMaxDelay() != null) {
+ MinMaxDelay mmDelay = new MinMaxDelayBuilder()
+ .setMaxDelay(new Delay(la.getLinkMinMaxDelay().getMaxDelay().getValue()))
+ .setMinDelay(new Delay(la.getLinkMinMaxDelay().getMinDelay().getValue())).build();
+ builder.setMinMaxDelay(mmDelay);
+ }
+ if (la.getDelayVariation() != null) {
+ builder.setJitter(new Delay(la.getDelayVariation().getValue()));
+ }
+ if (la.getLinkLoss() != null) {
+ builder.setLoss(new Loss(la.getLinkLoss().getValue()));
+ }
+ if (la.getAvailableBandwidth() != null) {
+ builder.setAvailableBandwidth(bandwithToDecimalBandwidth(la.getAvailableBandwidth()));
+ }
+ if (la.getResidualBandwidth() != null) {
+ builder.setResidualBandwidth(bandwithToDecimalBandwidth(la.getResidualBandwidth()));
+ }
+ if (la.getUtilizedBandwidth() != null) {
+ builder.setUtilizedBandwidth(bandwithToDecimalBandwidth(la.getUtilizedBandwidth()));
+ }
+ if (la.getSharedRiskLinkGroups() != null) {
+ List<Uint32> srlgs = new ArrayList<Uint32>();
+ for (SrlgId srlg : la.getSharedRiskLinkGroups()) {
+ srlgs.add(srlg.getValue());
+ }
+ builder.setSrlgs(srlgs);
+ }
+ if (la.getSrAdjIds() != null) {
+ for (SrAdjIds adj : la.getSrAdjIds()) {
+ if (adj.getSidLabelIndex() instanceof LocalLabelCase) {
+ boolean backup = false;
+ if (adj.getFlags() instanceof OspfAdjFlags) {
+ backup = ((OspfAdjFlags) adj.getFlags()).isBackup();
+ }
+ if (adj.getFlags() instanceof IsisAdjFlags) {
+ backup = ((IsisAdjFlags) adj.getFlags()).isBackup();
+ }
+ if (!backup) {
+ builder.setAdjSid(((LocalLabelCase) adj.getSidLabelIndex()).getLocalLabel().getValue());
+ } else {
+ builder.setBackupAdjSid(((LocalLabelCase) adj.getSidLabelIndex()).getLocalLabel().getValue());
+ }
+ }
+ }
+ }
+ return builder.build();
+ }
+
+ /**
+ * Get Node Attributes from Link State Route attributes.
+ *
+ * @param attributes The attribute part from the Link State route
+ *
+ * @return Node Attributes
+ */
+ private NodeAttributes getNodeAttributes(final Attributes attributes) {
+ final NodeAttributes na;
+ final Attributes1 attr = attributes.augmentation(Attributes1.class);
+ if (attr != null) {
+ final LinkStateAttribute attrType = attr.getLinkStateAttribute();
+ if (attrType != null) {
+ na = ((NodeAttributesCase) attrType).getNodeAttributes();
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ return na;
+ }
+
+ /**
+ * Create Vertex from the Node Attributes.
+ *
+ * @param na Node Attributes
+ * @param cvertex Connected Vertex associated to this Vertex
+ * @param as As number
+ *
+ * @return New Vertex
+ */
+ private Vertex getVertex(NodeAttributes na, Uint64 id, int as) {
+ VertexBuilder builder = new VertexBuilder().setVertexId(id).setAsn(Uint32.valueOf(as));
+ if (na.getIpv4RouterId() != null) {
+ builder.setRouterId(new IpAddress(new Ipv4Address(na.getIpv4RouterId().getValue())));
+ }
+ if (na.getIpv6RouterId() != null) {
+ builder.setRouterId(new IpAddress(new Ipv6Address(na.getIpv6RouterId().getValue())));
+ }
+ /*
+ * Set Router Name with dynamic hostname (IS-IS) or IPv4 address in dot decimal format (OSPF)
+ */
+ if (na.getDynamicHostname() != null) {
+ builder.setName(na.getDynamicHostname());
+ } else {
+ int key = id.intValue();
+ builder.setName(
+ ((key << 24) & 0xFF) + "." + ((key << 16) & 0xFF) + "." + ((key << 8) & 0xFF) + "." + (key & 0xFF));
+ }
+ if (na.getSrCapabilities() != null) {
+ builder.setSrgb(new SrgbBuilder()
+ .setLowerBound(
+ ((LocalLabelCase) na.getSrCapabilities().getSidLabelIndex()).getLocalLabel().getValue())
+ .setRangeSize(na.getSrCapabilities().getRangeSize().getValue())
+ .build());
+ }
+ if (na.getNodeFlags() != null) {
+ if (na.getNodeFlags().isAbr()) {
+ builder.setVertexType(VertexType.Abr);
+ }
+ if (na.getNodeFlags().isExternal()) {
+ builder.setVertexType(VertexType.AsbrOut);
+ }
+ } else {
+ builder.setVertexType(VertexType.Standard);
+ }
+ return builder.build();
+ }
+
+ /**
+ * Create new Connected Vertex in the Connected Graph.
+ *
+ * @param value The complete Linkstate route information
+ * @param nodeCase The node part of the Linkstate route
+ * @param attributes The node attributes
+ */
+ private void createVertex(final LinkstateRoute value, final NodeCase nodeCase, final Attributes attributes) {
+ Preconditions.checkArgument(nodeCase != null, "Missing Node Case. Skip this Node");
+ Preconditions.checkArgument(nodeCase.getNodeDescriptors() != null, "Missing Node Descriptors. Skip this Node");
+
+ Uint64 vertexId = getVertexId(nodeCase.getNodeDescriptors().getCRouterIdentifier());
+ if (vertexId == Uint64.ZERO) {
+ LOG.warn("Unable to get Vertex Identifier from descriptor {}, skipping it", nodeCase.getNodeDescriptors());
+ return;
+ }
+
+ NodeAttributes na = getNodeAttributes(attributes);
+ if (na == null) {
+ LOG.warn("Missing attributes in node {} route {}, skipping it", nodeCase, value);
+ return;
+ }
+
+ int asNumber = 0;
+ if (nodeCase.getNodeDescriptors() != null) {
+ asNumber = nodeCase.getNodeDescriptors().getAsNumber().getValue().intValue();
+ }
+ Vertex vertex = getVertex(na, vertexId, asNumber);
+
+ /* Add the Connected Vertex and associated Vertex in the Graph */
+ LOG.info("Add Vertex {} in TED[{}]", vertex.getName(), cgraph);
+ cgraph.addVertex(vertex);
+ }
+
+ /**
+ * Create new Prefix in the Connected Graph.
+ *
+ * @param value The complete Linkstate route information
+ * @param prefixCase The Prefix part of the Linkstate route
+ * @param attributes The Prefix attributes
+ */
+ private void createPrefix(final LinkstateRoute value, final PrefixCase prefixCase, final Attributes attributes) {
+ final IpPrefix ippfx = prefixCase.getPrefixDescriptors().getIpReachabilityInformation();
+ if (ippfx == null) {
+ LOG.warn("IP reachability not present in prefix {} route {}, skipping it", prefixCase, value);
+ return;
+ }
+
+ /* Verify that all mandatory information are present */
+ final PrefixAttributes pa;
+ final Attributes1 attr = attributes.augmentation(Attributes1.class);
+ if (attr != null) {
+ final LinkStateAttribute attrType = attr.getLinkStateAttribute();
+ if (attrType != null) {
+ pa = ((PrefixAttributesCase) attrType).getPrefixAttributes();
+ } else {
+ LOG.warn("Missing attribute type in IP {} prefix {} route {}, skipping it", ippfx, prefixCase, value);
+ return;
+ }
+ } else {
+ LOG.warn("Missing attributes in IP {} prefix {} route {}, skipping it", ippfx, prefixCase, value);
+ return;
+ }
+
+ /*
+ * Get Connected Vertex from Connected Graph corresponding to the
+ * Advertising Node Descriptor
+ */
+ Uint64 vertexId = getVertexId(prefixCase.getAdvertisingNodeDescriptors().getCRouterIdentifier());
+ if (vertexId == Uint64.ZERO) {
+ LOG.warn("Unable to get the Vertex Identifier from descriptor {}, skipping it",
+ prefixCase.getAdvertisingNodeDescriptors());
+ return;
+ }
+
+ /* Create Prefix */
+ PrefixBuilder builder = new PrefixBuilder().setVertexId(vertexId);
+ if (pa.getSrPrefix() != null && pa.getSrPrefix().getSidLabelIndex() instanceof SidCase) {
+ builder.setPrefixSid(((SidCase) pa.getSrPrefix().getSidLabelIndex()).getSid());
+ if (pa.getSrPrefix().getFlags() instanceof IsisPrefixFlagsCase) {
+ builder.setNodeSid(
+ ((IsisPrefixFlagsCase) pa.getSrPrefix().getFlags()).getIsisPrefixFlags().isNodeSid());
+ } else {
+ /*
+ * Seems that OSPF Flags are not accessible. Assuming that the
+ * Prefix is a Node SID
+ */
+ builder.setNodeSid(true);
+ }
+ }
+ if (ippfx.getIpv4Prefix() != null) {
+ builder.setPrefix(new IpPrefix(ippfx.getIpv4Prefix()));
+ }
+ if (ippfx.getIpv6Prefix() != null) {
+ builder.setPrefix(new IpPrefix(ippfx.getIpv6Prefix()));
+ }
+ Prefix prefix = builder.build();
+
+ /* Add the Prefix to the Connected Vertex within the Connected Graph */
+ LOG.info("Add prefix {} in TED[{}]", builder.getPrefix(), cgraph);
+ cgraph.addPrefix(prefix);
+ }
+
+ @Override
+ protected void removeObject(final ReadWriteTransaction trans, final InstanceIdentifier<LinkstateRoute> id,
+ final LinkstateRoute value) {
+ if (value == null) {
+ LOG.error("Empty before-data received in delete data change notification for instance id {}", id);
+ return;
+ }
+
+ final ObjectType t = value.getObjectType();
+ if (t instanceof LinkCase) {
+ removeEdge((LinkCase) t);
+ } else if (t instanceof NodeCase) {
+ removeVertex((NodeCase) t);
+ } else if (t instanceof PrefixCase) {
+ removePrefix((PrefixCase) t);
+ } else {
+ LOG.debug(UNHANDLED_OBJECT_CLASS, t.implementedInterface());
+ }
+ }
+
+ private void removeEdge(LinkCase linkCase) {
+ /* Get Source and Destination Connected Vertex */
+ if (linkCase.getLinkDescriptors() == null) {
+ LOG.warn("Missing Link descriptor in link {}, skipping it", linkCase);
+ return;
+ }
+ EdgeKey edgeKey = new EdgeKey(getEdgeId(linkCase));
+ if ((edgeKey == null) || (edgeKey.getEdgeId() == Uint64.ZERO)) {
+ LOG.warn("Unable to get the Edge Key from link {}, skipping it", linkCase);
+ return;
+ }
+
+ LOG.info("Deleted Edge {} from TED[{}]", edgeKey, cgraph);
+ cgraph.deleteEdge(edgeKey);
+ }
+
+ private void removeVertex(NodeCase nodeCase) {
+ VertexKey vertexKey = new VertexKey(getVertexId(nodeCase.getNodeDescriptors().getCRouterIdentifier()));
+ if ((vertexKey == null) || (vertexKey.getVertexId() == Uint64.ZERO)) {
+ LOG.warn("Unable to get Vertex Key from descriptor {}, skipping it", nodeCase.getNodeDescriptors());
+ return;
+ }
+
+ LOG.info("Deleted Vertex {} in TED[{}]", vertexKey, cgraph);
+ cgraph.deleteVertex(vertexKey);
+ }
+
+ private void removePrefix(PrefixCase prefixCase) {
+ final IpPrefix ippfx = prefixCase.getPrefixDescriptors().getIpReachabilityInformation();
+ if (ippfx == null) {
+ LOG.warn("IP reachability not present in prefix {}, skipping it", prefixCase);
+ return;
+ }
+
+ LOG.info("Deleted prefix {} in TED[{}]", ippfx, cgraph);
+ cgraph.deletePrefix(ippfx);
+ }
+
+ /**
+ * Get Vertex in the Graph by the OSPF Router ID or IS-IS-System ID.
+ *
+ * @param routerID The Router Identifier entry
+ *
+ * @return Vertex in the Connected Graph that corresponds to this Router ID. Vertex is created if not found.
+ */
+ private Uint64 getVertexId(CRouterIdentifier routerID) {
+ Long rid = 0L;
+
+ if (routerID instanceof IsisNodeCase) {
+ byte[] isoId = ((IsisNodeCase) routerID).getIsisNode().getIsoSystemId().getValue();
+ final byte[] convert = {0, 0, isoId[0], isoId[1], isoId[2], isoId[3], isoId[4], isoId[5]};
+ rid = ByteBuffer.wrap(convert).getLong();
+ }
+ if (routerID instanceof OspfNodeCase) {
+ rid = ((OspfNodeCase) routerID).getOspfNode().getOspfRouterId().longValue();
+ }
+
+ LOG.debug("Get Vertex Identifier {}", rid);
+ return Uint64.valueOf(rid);
+ }
+
+ private DecimalBandwidth bandwithToDecimalBandwidth(Bandwidth bw) {
+ return new DecimalBandwidth(BigDecimal.valueOf(ByteBuffer.wrap(bw.getValue()).getFloat()));
+ }
+
+ private long ipv4ToKey(String str) {
+ byte[] ip;
+ try {
+ ip = ((Inet4Address) Inet4Address.getByName(str)).getAddress();
+ } catch (UnknownHostException e) {
+ return 0;
+ }
+ return (((0xFF & ip[0]) << 24) | ((0xFF & ip[1]) << 16) | ((0xFF & ip[2]) << 8) | (0xFF & ip[3]));
+ }
+
+ private Long ipv6ToKey(String str) {
+ byte[] ip;
+ try {
+ ip = ((Inet6Address) Inet6Address.getByName(str)).getAddress();
+ } catch (UnknownHostException e) {
+ return 0L;
+ }
+ /* Keep only the lower 64bits from the IP address */
+ byte[] lowerIP = {ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]};
+ return ByteBuffer.wrap(lowerIP).getLong();
+ }
+
+ @Override
+ protected InstanceIdentifier<LinkstateRoute> getRouteWildcard(final InstanceIdentifier<Tables> tablesId) {
+ return tablesId.child(LinkstateRoutesCase.class, LinkstateRoutes.class).child(LinkstateRoute.class);
+ }
+
+ @Override
+ protected void clearTopology() {
+ cgraph.clear();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Orange. 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.bgpcep.bgp.topology.provider.config;
+
+import org.opendaylight.bgpcep.bgp.topology.provider.AbstractTopologyBuilder;
+import org.opendaylight.bgpcep.bgp.topology.provider.LinkstateGraphBuilder;
+import org.opendaylight.bgpcep.bgp.topology.provider.spi.BgpTopologyDeployer;
+import org.opendaylight.graph.ConnectedGraphProvider;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.protocol.bgp.rib.RibReference;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.topology.types.rev160524.TopologyTypes1;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+
+public final class LinkstateGraphProvider extends AbstractBgpTopologyProvider {
+
+ ConnectedGraphProvider graphProvider;
+
+ public LinkstateGraphProvider(final BgpTopologyDeployer deployer, final ConnectedGraphProvider graphProvider) {
+ super(deployer);
+ this.graphProvider = graphProvider;
+ }
+
+ @Override
+ AbstractTopologyBuilder<?> createTopologyBuilder(final DataBroker dataProvider, final RibReference locRibReference,
+ final TopologyId topologyId) {
+ return new LinkstateGraphBuilder(dataProvider, locRibReference, topologyId, this.graphProvider);
+ }
+
+ @Override
+ public boolean topologyTypeFilter(final Topology topology) {
+ final TopologyTypes1 topoAug = getTopologyAug(topology);
+ return topoAug != null && topoAug.getBgpLinkstateTopology() != null;
+ }
+}
<bean id="linkstateTopologyProvider" class="org.opendaylight.bgpcep.bgp.topology.provider.config.LinkstateTopologyProvider" destroy-method="close">
<argument ref="bgpTopologyDeployer"/>
</bean>
+
+ <reference id="connectedGraphProvider" interface="org.opendaylight.graph.ConnectedGraphProvider"/>
+ <bean id="linkstateGraphProvider" class="org.opendaylight.bgpcep.bgp.topology.provider.config.LinkstateGraphProvider" destroy-method="close">
+ <argument ref="bgpTopologyDeployer"/>
+ <argument ref="connectedGraphProvider"/>
+ </bean>
</blueprint>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>odl-bgpcep-algo</artifactId>
+ <artifactId>odl-bgpcep-algo-api</artifactId>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>odl-bgpcep-algo-api</artifactId>
+ <artifactId>odl-bgpcep-algo</artifactId>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<type>xml</type>
<classifier>features</classifier>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-bgpcep-graph</artifactId>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
<dependency>
<groupId>org.opendaylight.mdsal.model</groupId>
<artifactId>odl-mdsal-model-draft-clemm-netmod-yang-network-topo-01</artifactId>
<type>xml</type>
<classifier>features</classifier>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-bgpcep-pcep-server</artifactId>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-bgpcep-pcep-topology</artifactId>
<type>xml</type>
<classifier>features</classifier>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-bgpcep-pcep-server-provider</artifactId>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-bgpcep-pcep-p2mp-te-lsp</artifactId>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2020 Orange. 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>0.14.0-SNAPSHOT</version>
+ <relativePath>../../../single-feature-parent</relativePath>
+ </parent>
+
+ <artifactId>odl-bgpcep-pcep-server-provider</artifactId>
+ <packaging>feature</packaging>
+
+ <name>OpenDaylight :: PCEP :: PCE Server Provider</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-server-provider</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-bgpcep-pcep-server</artifactId>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-bgpcep-algo</artifactId>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2020 Orange. 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>0.14.0-SNAPSHOT</version>
+ <relativePath>../../../single-feature-parent</relativePath>
+ </parent>
+
+ <artifactId>odl-bgpcep-pcep-server</artifactId>
+ <packaging>feature</packaging>
+
+ <name>OpenDaylight :: PCEP :: PCE Server API</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-server-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-bgpcep-algo-api</artifactId>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ </dependencies>
+</project>
<type>xml</type>
<classifier>features</classifier>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-bgpcep-pcep-server-provider</artifactId>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
<dependency>
<groupId>org.opendaylight.mdsal</groupId>
<artifactId>odl-mdsal-dom-broker</artifactId>
<module>odl-bgpcep-pcep-impl</module>
<module>odl-bgpcep-programming-api</module>
<module>odl-bgpcep-programming-impl</module>
+ <module>odl-bgpcep-pcep-server</module>
<module>odl-bgpcep-pcep-topology</module>
<module>odl-bgpcep-pcep-stateful07</module>
+ <module>odl-bgpcep-pcep-server-provider</module>
<module>odl-bgpcep-pcep-topology-provider</module>
<module>odl-bgpcep-pcep-tunnel-provider</module>
<module>odl-bgpcep-pcep-segment-routing</module>
<packaging>pom</packaging>
<modules>
- <module>bgp</module>
- <module>pcep</module>
<module>graph</module>
+ <module>bgp</module>
<module>algo</module>
+ <module>pcep</module>
<module>bgpcep-extras</module>
<module>bmp</module>
<module>rsvp</module>
<artifactId>pcep-segment-routing</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-server-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-server-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>pcep-topology-api</artifactId>
<type>xml</type>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-bgpcep-pcep-server</artifactId>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-bgpcep-pcep-topology</artifactId>
<type>xml</type>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-bgpcep-pcep-server-provider</artifactId>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-bgpcep-pcep-topology-provider</artifactId>
<module>ietf-stateful07</module>
<module>ietf-p2mp-te-lsp</module>
<module>testtool</module>
+ <module>server</module>
<module>topology</module>
<module>segment-routing</module>
<module>pcc-mock</module>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2020 Orange. 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.odlparent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>6.0.4</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <artifactId>pcep-server-parent</artifactId>
+ <version>0.14.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <description>Path Computation Element Server</description>
+ <name>${project.artifactId}</name>
+
+ <modules>
+ <module>server-api</module>
+ <module>server-provider</module>
+ </modules>
+
+ <properties>
+ <maven.deploy.skip>true</maven.deploy.skip>
+ <maven.install.skip>true</maven.install.skip>
+ </properties>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2019 Orange Labs. 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>0.14.0-SNAPSHOT</version>
+ <relativePath>../../../binding-parent</relativePath>
+ </parent>
+
+ <artifactId>pcep-server-api</artifactId>
+ <description>Path Computation Server API</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>graph-api</artifactId>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2020 Orange. 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.bgpcep.pcep.server;
+
+import java.util.List;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Message;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bandwidth.object.Bandwidth;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.classtype.object.ClassType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.object.EndpointsObj;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.Ero;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.Metrics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.Requests;
+
+public interface PathComputation {
+
+ Message computePath(Requests req);
+
+ Ero computeEro(EndpointsObj endpoints, Bandwidth bandwidth, ClassType classType, List<Metrics> metrics,
+ boolean segmentRouting);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Orange. 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.bgpcep.pcep.server;
+
+import org.opendaylight.graph.ConnectedGraph;
+
+public interface PceServerProvider {
+
+ PathComputation getPathComputation();
+
+ ConnectedGraph getTedGraph();
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2019 Orange Labs 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
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <artifactId>bgpcep-parent</artifactId>
+ <version>0.14.0-SNAPSHOT</version>
+ <relativePath>../../../parent</relativePath>
+ </parent>
+
+ <artifactId>pcep-server-provider</artifactId>
+ <description>PCE Server Provider</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-server-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>graph-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>algo-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>concepts</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-spi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-segment-routing</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rsvp-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
+ <artifactId>rfc6991-ietf-inet-types</artifactId>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2020 Orange. 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.bgpcep.pcep.server.provider;
+
+import com.google.common.collect.Lists;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ieee754.rev130819.Float32;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.ConstrainedPath;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.path.descriptions.PathDescription;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.Pcerr;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.PcerrBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.Pcrep;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.PcrepBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.SidType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.pcrep.pcrep.message.replies.result.success._case.success.paths.ero.subobject.subobject.type.SrEroType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.pcrep.pcrep.message.replies.result.success._case.success.paths.ero.subobject.subobject.type.SrEroTypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.sr.subobject.nai.IpNodeIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.NoPathVectorTlv.Flags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.RequestId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bandwidth.object.BandwidthBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.classtype.object.ClassTypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.Ero;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.EroBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.ero.Subobject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.ero.SubobjectBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.Metrics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.MetricsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.metric.object.MetricBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcep.error.object.ErrorObjectBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.PcerrMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.ErrorsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.error.type.RequestCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.error.type.request._case.RequestBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.error.type.request._case.request.RpsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.PcrepMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.RepliesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.FailureCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.SuccessCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.failure._case.NoPathBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.failure._case.no.path.TlvsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.failure._case.no.path.tlvs.NoPathVectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.success._case.SuccessBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.success._case.success.Paths;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.success._case.success.PathsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.P2p;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.rp.object.Rp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.rp.object.RpBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.IpPrefixCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.IpPrefixCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefixBuilder;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint8;
+
+public final class MessagesUtil {
+
+ public static final byte NO_PATH = 0x0;
+ public static final byte UNKNOWN_SOURCE = 0x1;
+ public static final byte UNKNOWN_DESTINATION = 0x0;
+
+ /*
+ * See
+ * https://www.iana.org/assignments/pcep/pcep.xhtml#metric-object-ni-field
+ */
+ public static final int IGP_METRIC = 1;
+ public static final int TE_METRIC = 2;
+ public static final int PATH_DELAY = 12;
+
+ private MessagesUtil() {
+ throw new UnsupportedOperationException();
+ }
+
+ public static Ero getEro(List<PathDescription> pathDescriptions) {
+ /* Prepare ERO */
+ final EroBuilder eroBuilder = new EroBuilder();
+ eroBuilder.setIgnore(false);
+ eroBuilder.setProcessingRule(true);
+ final List<Subobject> eroSubs = new ArrayList<>();
+
+ /* Fulfill ERO sublist */
+ for (PathDescription path : pathDescriptions) {
+ Subobject sb = null;
+ if (path.getLabel() == null) {
+ IpPrefix ipPref = null;
+ /* Prepare SubObject for IPv4 or IPv6 address */
+ if (path.getIpv4() != null) {
+ final Ipv4Prefix ipv4Pref = new Ipv4Prefix(path.getIpv4().getValue() + "/32");
+ ipPref = new IpPrefixBuilder().setIpPrefix(
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715
+ .IpPrefix(ipv4Pref))
+ .build();
+ }
+ if (path.getIpv6() != null) {
+ final Ipv6Prefix ipv6Pref = new Ipv6Prefix(path.getIpv6().getValue() + "/128");
+ ipPref = new IpPrefixBuilder().setIpPrefix(
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715
+ .IpPrefix(ipv6Pref))
+ .build();
+ }
+ if (ipPref != null) {
+ final IpPrefixCase ipPrefCase = new IpPrefixCaseBuilder().setIpPrefix(ipPref).build();
+ sb = new SubobjectBuilder().setSubobjectType(ipPrefCase).setLoose(false).build();
+ }
+ } else {
+ /* Prepare SubObject for Segment Routing */
+ SrEroType srEro = null;
+ if (path.getIpv4() != null) {
+ srEro = new SrEroTypeBuilder()
+ .setSidType(SidType.Ipv4NodeId)
+ .setSid(path.getLabel().getValue())
+ .setCFlag(false)
+ .setMFlag(false)
+ .setNai(new IpNodeIdBuilder()
+ .setIpAddress(new IpAddressNoZone(new Ipv4AddressNoZone(path.getIpv4().getValue())))
+ .build())
+ .build();
+ }
+ if (path.getIpv6() != null) {
+ srEro = new SrEroTypeBuilder()
+ .setSidType(SidType.Ipv6NodeId)
+ .setSid(path.getLabel().getValue())
+ .setCFlag(false)
+ .setMFlag(false)
+ .setNai(new IpNodeIdBuilder()
+ .setIpAddress(new IpAddressNoZone(new Ipv6AddressNoZone(path.getIpv6().getValue())))
+ .build())
+ .build();
+ }
+ if (srEro != null) {
+ sb = new SubobjectBuilder().setSubobjectType(srEro).setLoose(false).build();
+ }
+ }
+
+ /* Add corresponding SubObject to the ERO List */
+ if (sb != null) {
+ eroSubs.add(sb);
+ }
+ }
+ /* Set ERO sublist */
+ eroBuilder.setSubobject(eroSubs);
+
+ return eroBuilder.build();
+ }
+
+ private static PathsBuilder buildPath(ConstrainedPath cpath) {
+ final PathsBuilder pathBuilder = new PathsBuilder();
+
+ /* Get ERO from Path Description */
+ pathBuilder.setEro(getEro(cpath.getPathDescription()));
+
+ /* Fulfill Computed Metrics if available */
+ final ArrayList<Metrics> metrics = new ArrayList<Metrics>();
+ if (cpath.getMetric() != null) {
+ final MetricBuilder metricBuilder = new MetricBuilder().setComputed(true)
+ .setMetricType(Uint8.valueOf(IGP_METRIC)).setValue(new Float32(
+ ByteBuffer.allocate(4).putFloat(Float.valueOf(cpath.getMetric().floatValue())).array()));
+ metrics.add(new MetricsBuilder().setMetric(metricBuilder.build()).build());
+ }
+ if (cpath.getTeMetric() != null) {
+ final MetricBuilder metricBuilder = new MetricBuilder().setComputed(true)
+ .setMetricType(Uint8.valueOf(TE_METRIC)).setValue(new Float32(
+ ByteBuffer.allocate(4).putFloat(Float.valueOf(cpath.getTeMetric().floatValue())).array()));
+ metrics.add(new MetricsBuilder().setMetric(metricBuilder.build()).build());
+ }
+ if (cpath.getDelay() != null) {
+ final MetricBuilder metricBuilder = new MetricBuilder().setComputed(true)
+ .setMetricType(Uint8.valueOf(PATH_DELAY)).setValue(new Float32(ByteBuffer.allocate(4)
+ .putFloat(Float.valueOf(cpath.getDelay().getValue().floatValue())).array()));
+ metrics.add(new MetricsBuilder().setMetric(metricBuilder.build()).build());
+ }
+ if (!metrics.isEmpty()) {
+ pathBuilder.setMetrics(metrics);
+ }
+ /* Fulfill Bandwidth and ClassType if set */
+ if (cpath.getBandwidth() != null) {
+ final BandwidthBuilder bwBuilder = new BandwidthBuilder();
+ bwBuilder.setBandwidth(new Bandwidth(new Float32(ByteBuffer.allocate(4)
+ .putFloat(Float.valueOf(cpath.getBandwidth().getValue().floatValue())).array())));
+ pathBuilder.setBandwidth(bwBuilder.build());
+ if (cpath.getClassType() != null) {
+ pathBuilder.setClassType(new ClassTypeBuilder().setClassType(
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109
+ .ClassType(cpath.getClassType()))
+ .build());
+ }
+ }
+ return pathBuilder;
+ }
+
+ public static Pcrep createPcRepMessage(Rp rp, P2p p2p, ConstrainedPath cpath) {
+
+ /* Prepare Path Object with ERO and Object from the Request */
+ final ArrayList<Paths> paths = new ArrayList<Paths>();
+ PathsBuilder pathBuilder = buildPath(cpath);
+
+ if (p2p.getLspa() != null) {
+ pathBuilder.setLspa(p2p.getLspa());
+ }
+ if (p2p.getIro() != null) {
+ pathBuilder.setIro(p2p.getIro());
+ }
+ if (p2p.getXro() != null) {
+ pathBuilder.setXro(p2p.getXro());
+ }
+ paths.add(pathBuilder.build());
+
+ /* Prepare Reply with Path Object */
+ final RepliesBuilder replyBuilder = new RepliesBuilder()
+ .setRp(rp)
+ .setResult(new SuccessCaseBuilder().setSuccess(new SuccessBuilder().setPaths(paths).build()).build());
+
+ /* Prepare PcRep Message */
+ final PcrepMessageBuilder msgBuilder = new PcrepMessageBuilder()
+ .setReplies(Lists.newArrayList(replyBuilder.build()));
+ return new PcrepBuilder().setPcrepMessage(msgBuilder.build()).build();
+ }
+
+ public static Pcrep createNoPathMessage(Rp rp, byte reason) {
+
+ /* Prepare NoPath Object */
+ final Flags flags = new Flags(false, false, false, false, false, false,
+ (reason == UNKNOWN_DESTINATION) ? true : false, (reason == UNKNOWN_SOURCE) ? true : false);
+ final NoPathVectorBuilder npvBuilder = new NoPathVectorBuilder().setFlags(flags);
+ final TlvsBuilder tlvsBuilder = new TlvsBuilder().setNoPathVector(npvBuilder.build());
+ final NoPathBuilder npBuilder = new NoPathBuilder()
+ .setProcessingRule(false)
+ .setIgnore(false)
+ .setNatureOfIssue(Uint8.ZERO)
+ .setUnsatisfiedConstraints(true)
+ .setTlvs(tlvsBuilder.build());
+
+ /* Prepare Reply */
+ final RepliesBuilder replyBuilder = new RepliesBuilder()
+ .setRp(rp)
+ .setResult(new FailureCaseBuilder().setNoPath(npBuilder.build()).build());
+
+ /* Prepare PcRep Message */
+ final PcrepMessageBuilder msgBuilder = new PcrepMessageBuilder()
+ .setReplies(Lists.newArrayList(replyBuilder.build()));
+ return new PcrepBuilder().setPcrepMessage(msgBuilder.build()).build();
+ }
+
+ public static Pcerr createErrorMsg(@NonNull final PCEPErrors pcepErrors, final Uint32 reqID) {
+ final PcerrMessageBuilder msgBuilder = new PcerrMessageBuilder();
+ return new PcerrBuilder().setPcerrMessage(msgBuilder
+ .setErrorType(
+ new RequestCaseBuilder().setRequest(new RequestBuilder()
+ .setRps(Lists
+ .newArrayList(new RpsBuilder().setRp(new RpBuilder().setProcessingRule(false)
+ .setIgnore(false).setRequestId(new RequestId(reqID)).build()).build()))
+ .build()).build())
+ .setErrors(Collections.singletonList(new ErrorsBuilder().setErrorObject(new ErrorObjectBuilder()
+ .setType(pcepErrors.getErrorType()).setValue(pcepErrors.getErrorValue()).build()).build()))
+ .build()).build();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Orange. 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.bgpcep.pcep.server.provider;
+
+import com.google.common.base.Preconditions;
+import java.math.BigDecimal;
+import java.nio.ByteBuffer;
+import java.util.List;
+import org.opendaylight.algo.PathComputationAlgorithm;
+import org.opendaylight.algo.PathComputationProvider;
+import org.opendaylight.bgpcep.pcep.server.PathComputation;
+import org.opendaylight.graph.ConnectedGraph;
+import org.opendaylight.graph.ConnectedVertex;
+import org.opendaylight.protocol.pcep.spi.PCEPErrors;
+import org.opendaylight.protocol.pcep.spi.PSTUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.DecimalBandwidth;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.Delay;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.VertexKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.AlgorithmType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.ComputationStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.ConstrainedPath;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.PathConstraints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.PathConstraints.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.get.constrained.path.input.ConstraintsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Message;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bandwidth.object.Bandwidth;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.classtype.object.ClassType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.address.family.Ipv4Case;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.address.family.Ipv6Case;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.object.EndpointsObj;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.Ero;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.Metrics;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.Requests;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.P2p;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint8;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PathComputationImpl implements PathComputation {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PathComputationImpl.class);
+
+ private final ConnectedGraph tedGraph;
+ private final PathComputationProvider algoProvider;
+
+ public PathComputationImpl(ConnectedGraph tedGraph, PathComputationProvider algoProvider) {
+ Preconditions.checkArgument(tedGraph != null);
+ this.tedGraph = tedGraph;
+ this.algoProvider = algoProvider;
+ }
+
+ @Override
+ public Message computePath(Requests req) {
+ LOG.info("Received Compute Path request");
+
+ /* Check that Request Parameter Object is present */
+ if (req == null || req.getRp() == null) {
+ LOG.error("Missing Request Parameter Objects. Abort!");
+ return MessagesUtil.createErrorMsg(PCEPErrors.RP_MISSING, Uint32.ZERO);
+ }
+
+ LOG.debug("Request for path computation {}", req);
+
+ /*
+ * Check that mandatory End Point Objects are present and Source /
+ * Destination are know in the TED Graph
+ */
+ P2p input = req.getSegmentComputation().getP2p();
+ if (input == null || input.getEndpointsObj() == null) {
+ LOG.error("Missing End Point Objects. Abort!");
+ Uint32 reqID = req.getRp().getRequestId().getValue();
+ return MessagesUtil.createErrorMsg(PCEPErrors.END_POINTS_MISSING, reqID);
+ }
+ VertexKey source = getSourceVertexKey(input.getEndpointsObj());
+ VertexKey destination = getDestinationVertexKey(input.getEndpointsObj());
+ if (source == null) {
+ return MessagesUtil.createNoPathMessage(req.getRp(), MessagesUtil.UNKNOWN_SOURCE);
+ }
+ if (destination == null) {
+ return MessagesUtil.createNoPathMessage(req.getRp(), MessagesUtil.UNKNOWN_DESTINATION);
+ }
+
+ /* Create new Constraints Object from the request */
+ PathConstraints cts = getConstraints(input, !PSTUtil.isDefaultPST(req.getRp().getTlvs().getPathSetupType()));
+
+ /* Determine Path Computation Algorithm according to Input choice */
+ AlgorithmType algoType;
+ if ((cts.getTeMetric() == null) && (cts.getDelay() == null)) {
+ algoType = AlgorithmType.Spf;
+ } else if (cts.getDelay() == null) {
+ algoType = AlgorithmType.Cspf;
+ } else {
+ algoType = AlgorithmType.Samcra;
+ }
+ PathComputationAlgorithm algo = algoProvider.getPathComputationAlgorithm(tedGraph, algoType);
+ if (algo == null) {
+ return MessagesUtil.createErrorMsg(PCEPErrors.RESOURCE_LIMIT_EXCEEDED, Uint32.ZERO);
+ }
+
+ /* Request Path Computation for given source, destination and constraints */
+ LOG.debug("Call Path Computation {} algorithm for path from {} to {} with contraints {}",
+ algoType, source, destination, cts);
+ final ConstrainedPath cpath = algo.computeP2pPath(source, destination, cts);
+
+ LOG.info("Computed path: {}", cpath.getPathDescription());
+
+ /* Check if we got a valid Path and return appropriate message */
+ if (cpath.getStatus() == ComputationStatus.Completed) {
+ return MessagesUtil.createPcRepMessage(req.getRp(), req.getSegmentComputation().getP2p(), cpath);
+ } else {
+ return MessagesUtil.createNoPathMessage(req.getRp(), MessagesUtil.NO_PATH);
+ }
+ }
+
+ @Override
+ public Ero computeEro(EndpointsObj endpoints, Bandwidth bandwidth, ClassType classType, List<Metrics> metrics,
+ boolean segmentRouting) {
+ VertexKey source = getSourceVertexKey(endpoints);
+ VertexKey destination = getDestinationVertexKey(endpoints);
+ if (source == null) {
+ return null;
+ }
+ if (destination == null) {
+ return null;
+ }
+ /* Create new Constraints Object from the request */
+ PathConstraints cts = getConstraints(endpoints, bandwidth, classType, metrics, segmentRouting);
+
+ /* Determine Path Computation Algorithm according to parameters */
+ AlgorithmType algoType;
+ if ((cts.getTeMetric() == null) && (cts.getDelay() == null) && (cts.getBandwidth() == null)) {
+ algoType = AlgorithmType.Spf;
+ } else if (cts.getDelay() == null) {
+ algoType = AlgorithmType.Cspf;
+ } else {
+ algoType = AlgorithmType.Samcra;
+ }
+ PathComputationAlgorithm algo = algoProvider.getPathComputationAlgorithm(tedGraph, algoType);
+ if (algo == null) {
+ return null;
+ }
+
+ /*
+ * Request Path Computation for given source, destination and
+ * constraints
+ */
+ final ConstrainedPath cpath = algo.computeP2pPath(source, destination, cts);
+
+ LOG.info("Computed ERO: {}", cpath.getPathDescription());
+
+ /* Check if we got a valid Path and return appropriate ERO */
+ if (cpath.getStatus() == ComputationStatus.Completed) {
+ return MessagesUtil.getEro(cpath.getPathDescription());
+ } else {
+ return null;
+ }
+ }
+
+ private VertexKey getSourceVertexKey(EndpointsObj endPoints) {
+ IpAddress address = null;
+
+ if (endPoints.getAddressFamily() instanceof Ipv4Case) {
+ address = new IpAddress(((Ipv4Case) endPoints.getAddressFamily()).getIpv4().getSourceIpv4Address());
+ }
+ if (endPoints.getAddressFamily() instanceof Ipv6Case) {
+ address = new IpAddress(((Ipv6Case) endPoints.getAddressFamily()).getIpv6().getSourceIpv6Address());
+ }
+ if (address == null) {
+ return null;
+ }
+
+ ConnectedVertex vertex = tedGraph.getConnectedVertex(address);
+ LOG.debug("Compute path from Source {}", vertex.toString());
+ return (vertex != null) ? vertex.getVertex().key() : null;
+ }
+
+ private VertexKey getDestinationVertexKey(EndpointsObj endPoints) {
+ IpAddress address = null;
+
+ if (endPoints.getAddressFamily() instanceof Ipv4Case) {
+ address = new IpAddress(((Ipv4Case) endPoints.getAddressFamily()).getIpv4().getDestinationIpv4Address());
+ }
+ if (endPoints.getAddressFamily() instanceof Ipv6Case) {
+ address = new IpAddress(((Ipv6Case) endPoints.getAddressFamily()).getIpv6().getDestinationIpv6Address());
+ }
+ if (address == null) {
+ return null;
+ }
+
+ ConnectedVertex vertex = tedGraph.getConnectedVertex(address);
+ LOG.debug("Compute path to Destination {}", vertex.toString());
+ return (vertex != null) ? vertex.getVertex().key() : null;
+ }
+
+ private PathConstraints getConstraints(P2p parameters, boolean segmentRouting) {
+ return getConstraints(parameters.getEndpointsObj(), parameters.getBandwidth(), parameters.getClassType(),
+ parameters.getMetrics(), segmentRouting);
+ }
+
+ private PathConstraints getConstraints(EndpointsObj endpoints, Bandwidth bandwidth, ClassType classType,
+ List<Metrics> metrics, boolean segmentRouting) {
+ ConstraintsBuilder ctsBuilder = new ConstraintsBuilder();
+ Float convert;
+
+ /* Set Metrics if any */
+ if (metrics != null) {
+ for (Metrics metric : metrics) {
+ convert = ByteBuffer.wrap(metric.getMetric().getValue().getValue()).getFloat();
+ switch (metric.getMetric().getMetricType().intValue()) {
+ case MessagesUtil.IGP_METRIC:
+ ctsBuilder.setMetric(Uint32.valueOf(convert.longValue()));
+ break;
+ case MessagesUtil.TE_METRIC:
+ ctsBuilder.setTeMetric(Uint32.valueOf(convert.longValue()));
+ break;
+ case MessagesUtil.PATH_DELAY:
+ ctsBuilder.setDelay(new Delay(Uint32.valueOf(convert.longValue())));
+ break;
+ default:
+ LOG.warn("Metric {} is not handle by Path Computation Constraints", metric);
+ break;
+ }
+ }
+ }
+
+ /* Set Bandwidth and Class Type */
+ if (bandwidth != null) {
+ convert = ByteBuffer.wrap(bandwidth.getBandwidth().getValue()).getFloat();
+ ctsBuilder.setBandwidth(new DecimalBandwidth(BigDecimal.valueOf(convert.longValue())));
+ if (classType != null) {
+ ctsBuilder.setClassType(classType.getClassType().getValue());
+ } else {
+ ctsBuilder.setClassType(Uint8.ZERO);
+ }
+ }
+
+ /* Set Address Family */
+ if (endpoints.getAddressFamily() instanceof Ipv4Case) {
+ if (segmentRouting) {
+ ctsBuilder.setAddressFamily(AddressFamily.SrIpv4);
+ } else {
+ ctsBuilder.setAddressFamily(AddressFamily.Ipv4);
+ }
+ } else {
+ if (segmentRouting) {
+ ctsBuilder.setAddressFamily(AddressFamily.SrIpv6);
+ } else {
+ ctsBuilder.setAddressFamily(AddressFamily.Ipv6);
+ }
+ }
+
+ return ctsBuilder.build();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Orange. 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.bgpcep.pcep.server.provider;
+
+import com.google.common.base.Preconditions;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.algo.PathComputationProvider;
+import org.opendaylight.bgpcep.pcep.server.PceServerProvider;
+import org.opendaylight.graph.ConnectedGraph;
+import org.opendaylight.graph.ConnectedGraphProvider;
+
+public class PceServerFactory implements PceServerProvider {
+
+ private final ConnectedGraphProvider graphProvider;
+ private final PathComputationProvider algoProvider;
+ private ConnectedGraph tedGraph = null;
+
+ public PceServerFactory(ConnectedGraphProvider graphProvider, PathComputationProvider pathComputationProvider) {
+ Preconditions.checkArgument(graphProvider != null);
+ this.graphProvider = graphProvider;
+ this.algoProvider = pathComputationProvider;
+ setTedGraph();
+ }
+
+ /**
+ * Set Traffic Engineering Graph. This method is necessary as the TedGraph could be available
+ * after the PathComputationFactory start e.g. manual insertion of a ted Graph, or late tedGraph fulfillment
+ * from BGP Link State.
+ */
+ private void setTedGraph() {
+ for (ConnectedGraph cgraph : this.graphProvider.getConnectedGraphs()) {
+ if (cgraph.getGraph().getName().startsWith("ted://")) {
+ this.tedGraph = cgraph;
+ break;
+ }
+ }
+ }
+
+ @Override
+ public PathComputationImpl getPathComputation() {
+ /* Leave a change to get a valid Graph */
+ if (tedGraph == null) {
+ setTedGraph();
+ }
+ return new PathComputationImpl(tedGraph, algoProvider);
+ }
+
+ @Override
+ public @Nullable ConnectedGraph getTedGraph() {
+ /* Leave a change to get a valid Graph in case of late fulfillment */
+ if (tedGraph == null) {
+ setTedGraph();
+ }
+ return this.tedGraph;
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2020 Orange. 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
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0">
+
+ <reference id="pathComputationProvider" interface="org.opendaylight.algo.PathComputationProvider"/>
+ <reference id="connectedGraphProvider" interface="org.opendaylight.graph.ConnectedGraphProvider" />
+
+ <bean id="pceServerProvider" class="org.opendaylight.bgpcep.pcep.server.provider.PceServerFactory">
+ <argument ref="connectedGraphProvider"/>
+ <argument ref="pathComputationProvider"/>
+ </bean>
+
+ <service ref="pceServerProvider" interface="org.opendaylight.bgpcep.pcep.server.PceServerProvider"/>
+
+</blueprint>
<groupId>${project.groupId}</groupId>
<artifactId>pcep-topology-spi</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>pcep-server-api</artifactId>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>programming-api</artifactId>
PCEPDispatcherDependencies getPCEPDispatcherDependencies() {
return this.pcepDispatcherDependencies;
}
+
+ PCEPTopologyProviderDependencies getPCEPTopologyProviderDependencies() {
+ return this.dependenciesProvider;
+ }
}
\ No newline at end of file
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import org.checkerframework.checker.lock.qual.GuardedBy;
+import org.opendaylight.bgpcep.pcep.server.PathComputation;
+import org.opendaylight.bgpcep.pcep.server.PceServerProvider;
import org.opendaylight.protocol.pcep.PCEPSession;
import org.opendaylight.protocol.pcep.spi.PCEPErrors;
import org.opendaylight.protocol.pcep.spi.PSTUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.srp.object.SrpBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.stateful.capability.tlv.Stateful;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev181109.symbolic.path.name.tlv.SymbolicPathNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.Pcreq;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Message;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.PcerrMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.EroBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.open.object.open.Tlvs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.path.setup.type.tlv.PathSetupType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.PcreqMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.AddLspArgs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.EnsureLspOperationalInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.LspId;
private final AtomicBoolean lspUpdateCapability = new AtomicBoolean(false);
private final AtomicBoolean initiationCapability = new AtomicBoolean(false);
+ private PceServerProvider pceServerProvider;
+
/**
* Creates a new stateful topology session listener for given server session manager.
*/
Stateful07TopologySessionListener(final ServerSessionManager serverSessionManager) {
super(serverSessionManager);
+ this.pceServerProvider = serverSessionManager.getPCEPTopologyProviderDependencies().getPceServerProvider();
}
private static LspDbVersion geLspDbVersionTlv(final Lsp lsp) {
return pb.build();
}
+ private boolean handlePcreqMessage(final PcreqMessage message) {
+
+ LOG.info("Start PcRequest Message handler");
+
+ /* Get a Path Computation to compute the Path from the Request */
+ PathComputation pathComputation = this.pceServerProvider.getPathComputation();
+ Message rep = null;
+ for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq
+ .message.Requests req : message.getRequests()) {
+ LOG.debug("Process request {}", req);
+ rep = pathComputation.computePath(req);
+ SrpIdNumber repId = null;
+ if (req.getRp() != null) {
+ repId = new SrpIdNumber(req.getRp().getRequestId().getValue());
+ } else {
+ repId = new SrpIdNumber(Uint32.ZERO);
+ }
+ sendMessage(rep, repId, null);
+ }
+ return false;
+ }
+
@Override
protected synchronized boolean onMessage(final MessageContext ctx, final Message message) {
if (message instanceof PcerrMessage) {
return handleErrorMessage((PcerrMessage) message);
}
+ if (message instanceof Pcreq) {
+ LOG.info("PcReq detected. Start Request Message handler");
+ return handlePcreqMessage(((Pcreq) message).getPcreqMessage());
+ }
if (!(message instanceof PcrptMessage)) {
return true;
}
// Build the request
final RequestsBuilder rb = new RequestsBuilder();
- final Arguments2 args = this.input.getArguments().augmentation(Arguments2.class);
- final Lsp inputLsp = args != null ? args.getLsp() : null;
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120
+ .add.lsp.args.Arguments args = this.input.getArguments();
+ final Arguments2 args2 = args.augmentation(Arguments2.class);
+ final Lsp inputLsp = args2 != null ? args2.getLsp() : null;
if (inputLsp == null) {
return OperationResults.createUnsent(PCEPErrors.LSP_MISSING).future();
}
rb.fieldsFrom(this.input.getArguments());
+ /* Call Path Computation if an ERO was not provided */
+ boolean segmentRouting = !PSTUtil.isDefaultPST(args2.getPathSetupType());
+ if ((rb.getEro() == null)
+ || (rb.getEro().getSubobject() == null)
+ || (rb.getEro().getSubobject().size() == 0)) {
+
+ /* Get a Path Computation to compute the Path from the Arguments */
+ PathComputation pathComputation = pceServerProvider.getPathComputation();
+ rb.setEro(pathComputation.computeEro(args.getEndpointsObj(), args.getBandwidth(), args.getClassType(),
+ args.getMetrics(), segmentRouting));
+ }
+
final TlvsBuilder tlvsBuilder;
if (inputLsp.getTlvs() != null) {
tlvsBuilder = new TlvsBuilder(inputLsp.getTlvs());
final SrpBuilder srpBuilder = new SrpBuilder()
.setOperationId(nextRequest())
.setProcessingRule(Boolean.TRUE);
- if (!PSTUtil.isDefaultPST(args.getPathSetupType())) {
+ if (segmentRouting) {
srpBuilder.setTlvs(
new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf
.stateful.rev181109.srp.object.srp.TlvsBuilder()
- .setPathSetupType(args.getPathSetupType()).build());
+ .setPathSetupType(args2.getPathSetupType()).build());
}
rb.setSrp(srpBuilder.build());
import java.util.Hashtable;
import java.util.List;
import org.checkerframework.checker.lock.qual.GuardedBy;
+import org.opendaylight.bgpcep.pcep.server.PceServerProvider;
import org.opendaylight.bgpcep.pcep.topology.provider.PCEPTopologyProvider;
import org.opendaylight.bgpcep.pcep.topology.provider.TopologySessionListenerFactory;
import org.opendaylight.bgpcep.pcep.topology.spi.stats.TopologySessionStatsRegistry;
private final BundleContext bundleContext;
private final ClusterSingletonServiceProvider cssp;
private final TopologySessionStatsRegistry stateRegistry;
+ private final PceServerProvider pceServerProvider;
@GuardedBy("this")
private PCEPTopologyProviderBeanCSS pcepTopoProviderCSS;
final PCEPDispatcher pcepDispatcher,
final RpcProviderService rpcProviderRegistry,
final TopologySessionListenerFactory sessionListenerFactory,
- final TopologySessionStatsRegistry stateRegistry) {
+ final TopologySessionStatsRegistry stateRegistry,
+ final PceServerProvider pceServerProvider) {
this.cssp = requireNonNull(cssp);
this.bundleContext = requireNonNull(bundleContext);
this.pcepDispatcher = requireNonNull(pcepDispatcher);
this.sessionListenerFactory = requireNonNull(sessionListenerFactory);
this.rpcProviderRegistry = requireNonNull(rpcProviderRegistry);
this.stateRegistry = requireNonNull(stateRegistry);
+ this.pceServerProvider = requireNonNull(pceServerProvider);
final List<PCEPCapability> capabilities = this.pcepDispatcher.getPCEPSessionNegotiatorFactory()
.getPCEPSessionProposalFactory().getCapabilities();
final boolean statefulCapability = capabilities.stream().anyMatch(PCEPCapability::isStateful);
return this.stateRegistry;
}
+ @Override
+ public PceServerProvider getPceServerProvider() {
+ return this.pceServerProvider;
+ }
+
private static class PCEPTopologyProviderBeanCSS implements ClusterSingletonService, AutoCloseable {
private final ServiceGroupIdentifier sgi;
private final PCEPTopologyProvider pcepTopoProvider;
import com.google.common.annotations.Beta;
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.bgpcep.pcep.server.PceServerProvider;
import org.opendaylight.bgpcep.pcep.topology.provider.TopologySessionListenerFactory;
import org.opendaylight.bgpcep.pcep.topology.spi.stats.TopologySessionStatsRegistry;
import org.opendaylight.mdsal.binding.api.DataBroker;
* @return TopologySessionStateRegistry
*/
TopologySessionStatsRegistry getStateRegistry();
+
+ /**
+ * PCE Server Provider.
+ *
+ * @return PceServerProvider
+ */
+ PceServerProvider getPceServerProvider();
}
class="org.opendaylight.bgpcep.pcep.topology.provider.Stateful07TopologySessionListenerFactory"/>
<service ref="Stateful07TopologySessionListenerFactory"
interface="org.opendaylight.bgpcep.pcep.topology.provider.TopologySessionListenerFactory"/>
-
+
<reference id="dataBroker" interface="org.opendaylight.mdsal.binding.api.DataBroker"
odl:type="default"/>
<reference id="rpcProviderService" interface="org.opendaylight.mdsal.binding.api.RpcProviderService"/>
<reference id="intructionFactory" interface="org.opendaylight.bgpcep.programming.spi.InstructionSchedulerFactory"/>
<reference id="topologySessionStatsRegistry"
interface="org.opendaylight.bgpcep.pcep.topology.spi.stats.TopologySessionStatsRegistry"/>
+ <reference id="pceServerProvider" interface="org.opendaylight.bgpcep.pcep.server.PceServerProvider"/>
<bean id="pcepTopologyDeployer"
class="org.opendaylight.bgpcep.pcep.topology.provider.config.PCEPTopologyDeployerImpl"
<argument ref="rpcProviderService"/>
<argument ref="Stateful07TopologySessionListenerFactory"/>
<argument ref="topologySessionStatsRegistry"/>
+ <argument ref="pceServerProvider"/>
</bean>
</blueprint>
doReturn(RPC_TIMEOUT).when(this.sessionConfig).getRpcTimeout();
doReturn(TEST_TOPOLOGY_ID).when(this.topology).getTopologyId();
doReturn(Collections.emptyList()).when(this.topology).getNode();
+ doReturn(null).when(this.topologyDependencies).getPceServerProvider();
final PCEPTopologyConfiguration configDep = new PCEPTopologyConfiguration(this.sessionConfig, this.topology);
this.manager = new ServerSessionManager(this.topologyDependencies, listenerFactory, configDep);
<module>util</module>
<!-- Subsystems -->
+ <module>graph</module>
<module>bgp</module>
<module>bmp</module>
- <module>graph</module>
<module>algo</module>
<module>pcep</module>
<module>programming</module>