2 * Copyright (c) 2021 Orange. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.bgpcep.pcep.server.provider;
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.base.MoreObjects;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.ListenableFuture;
17 import com.google.common.util.concurrent.MoreExecutors;
18 import java.nio.ByteBuffer;
19 import java.util.Collections;
20 import java.util.List;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.opendaylight.graph.ConnectedEdge;
23 import org.opendaylight.graph.ConnectedEdgeTrigger;
24 import org.opendaylight.graph.ConnectedGraph;
25 import org.opendaylight.graph.ConnectedVertex;
26 import org.opendaylight.graph.ConnectedVertexTrigger;
27 import org.opendaylight.mdsal.binding.api.WriteTransaction;
28 import org.opendaylight.mdsal.common.api.CommitInfo;
29 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.Edge;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.Vertex;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.edge.attributes.UnreservedBandwidth;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ieee754.rev130819.Float32;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.topology.rev140113.NetworkTopologyRef;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev220324.AddressFamily;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev220324.ComputationStatus;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev220324.path.descriptions.PathDescription;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.Arguments2Builder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.Arguments3Builder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.object.LspBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.PathComputationClient1;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.PathStatus;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.PathType;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.ConfiguredLsp;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.ConfiguredLspBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.configured.lsp.ComputedPath;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.configured.lsp.IntendedPath;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.configured.lsp.intended.path.Constraints;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bandwidth.object.BandwidthBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.address.family.Ipv4CaseBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.address.family.Ipv6CaseBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.address.family.ipv4._case.Ipv4Builder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.address.family.ipv6._case.Ipv6Builder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.object.EndpointsObjBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.MetricsBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.metric.object.MetricBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.path.setup.type.tlv.PathSetupTypeBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.AddLsp;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.AddLspInput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.AddLspInputBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.AddLspOutput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.Node1;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.RemoveLsp;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.RemoveLspInput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.RemoveLspInputBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.RemoveLspOutput;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.UpdateLsp;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.UpdateLspInput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.UpdateLspInputBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.UpdateLspOutput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.add.lsp.args.ArgumentsBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.pcep.client.attributes.PathComputationClient;
77 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
78 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
79 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
80 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
81 import org.opendaylight.yangtools.yang.binding.CodeHelpers;
82 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
83 import org.opendaylight.yangtools.yang.common.RpcResult;
84 import org.opendaylight.yangtools.yang.common.Uint8;
85 import org.slf4j.Logger;
86 import org.slf4j.LoggerFactory;
88 public class ManagedTePath implements ConnectedEdgeTrigger, ConnectedVertexTrigger {
90 private ConfiguredLsp cfgLsp = null;
91 private ConfiguredLsp prevLsp = null;
92 private final ManagedTeNode teNode;
93 private boolean sent = false;
94 private boolean triggerFlag = false;
95 private PathType type = PathType.Pcc;
96 private final InstanceIdentifier<Topology> pcepTopology;
97 private final InstanceIdentifier<PathComputationClient1> pccIdentifier;
99 private static final Logger LOG = LoggerFactory.getLogger(ManagedTePath.class);
101 public ManagedTePath(ManagedTeNode teNode, InstanceIdentifier<Topology> topology) {
102 this.teNode = requireNonNull(teNode);
103 this.pcepTopology = requireNonNull(topology);
104 this.pccIdentifier = pcepTopology.child(Node.class, new NodeKey(teNode.getId())).augmentation(Node1.class)
105 .child(PathComputationClient.class).augmentation(PathComputationClient1.class);
108 public ManagedTePath(ManagedTeNode teNode, final ConfiguredLsp lsp, InstanceIdentifier<Topology> topology) {
109 this.cfgLsp = requireNonNull(lsp);
110 this.teNode = requireNonNull(teNode);
111 this.pcepTopology = requireNonNull(topology);
112 this.pccIdentifier = pcepTopology.child(Node.class, new NodeKey(teNode.getId())).augmentation(Node1.class)
113 .child(PathComputationClient.class).augmentation(PathComputationClient1.class);
116 public ManagedTePath(ManagedTeNode teNode, final ManagedTePath mngPath) {
117 checkArgument(mngPath != null, "Managed TE Path is mandatory. Can't be null or empty!");
118 this.cfgLsp = mngPath.getLsp();
119 this.sent = mngPath.isSent();
120 this.type = mngPath.getType();
121 this.teNode = requireNonNull(teNode);
122 this.pcepTopology = mngPath.getTopology();
123 this.pccIdentifier = pcepTopology.child(Node.class, new NodeKey(teNode.getId())).augmentation(Node1.class)
124 .child(PathComputationClient.class).augmentation(PathComputationClient1.class);
127 public ConfiguredLsp getLsp() {
131 public ManagedTeNode getManagedTeNode() {
135 public PathType getType() {
139 public InstanceIdentifier<Topology> getTopology() {
143 public ManagedTePath setConfiguredLsp(final ConfiguredLsp lsp) {
144 this.prevLsp = this.cfgLsp;
149 public ManagedTePath setType(PathType type) {
155 * Mark this TE Path as synchronized and update the Data Store accordingly.
159 this.cfgLsp = new ConfiguredLspBuilder(cfgLsp).setPathStatus(PathStatus.Sync).build();
164 * Disabling this TE Path by marking it as Configured. Do not update the Data Store.
166 public void disabled() {
167 this.cfgLsp = new ConfiguredLspBuilder(cfgLsp).setPathStatus(PathStatus.Configured).build();
171 * Mark this TE Path as Failed.
173 public void failed() {
174 this.cfgLsp = new ConfiguredLspBuilder(cfgLsp).setPathStatus(PathStatus.Failed).build();
178 public boolean isSent() {
183 * Compare the current TE Path against the reported LSP to determine if there are in Sync, need Update or
184 * considered as in Failure if already updated.
186 * @param lsp LSP that corresponds to the reported LSP
188 * @return new LSP status
190 public PathStatus checkReportedPath(final ConfiguredLsp lsp) {
191 /* Check if this path has not been already verified */
192 if (cfgLsp.getPathStatus() == PathStatus.Sync) {
193 return PathStatus.Sync;
196 /* Check Source, Destination and routing method which must be the same */
197 final IntendedPath iPath = lsp.getIntendedPath();
198 final IntendedPath rPath = lsp.getIntendedPath();
199 PathStatus newStatus = sent ? PathStatus.Failed : PathStatus.Updated;
200 if (!iPath.getSource().equals(rPath.getSource()) || !iPath.getDestination().equals(rPath.getDestination())) {
201 return PathStatus.Failed;
204 /* Check constraints ... */
205 final Constraints icts = iPath.getConstraints();
206 final Constraints rcts = rPath.getConstraints();
207 if (!icts.getAddressFamily().equals(rcts.getAddressFamily())) {
210 if (icts.getBandwidth() != null && !icts.getBandwidth().equals(rcts.getBandwidth())) {
214 * ClassType, TE metric and Delay are not supported by all routers: need
215 * to check them only if there are all present
217 if (icts.getClassType() != null && rcts.getClassType() != null
218 && !icts.getClassType().equals(rcts.getClassType())) {
221 if (icts.getTeMetric() != null && rcts.getTeMetric() != null
222 && !icts.getTeMetric().equals(rcts.getTeMetric())) {
225 if (icts.getDelay() != null && rcts.getDelay() != null && !icts.getDelay().equals(rcts.getDelay())) {
229 /* ... and Path to determine if an update is required */
230 if (lsp.getComputedPath().getComputationStatus() != ComputationStatus.Completed) {
231 return PathStatus.Failed;
233 if (!lsp.getComputedPath().getPathDescription().equals(lsp.getComputedPath().getPathDescription())) {
237 /* All is conform. LSP is in sync with expected result. */
238 return PathStatus.Sync;
241 private void configureGraph(ConnectedGraph graph, ComputedPath cpath, Constraints cts, boolean config) {
242 /* Check that Connected Graph is valid */
247 /* Verify that we have a valid Computed Path and that the LSP is in SYNC */
248 if (cpath.getComputationStatus() != ComputationStatus.Completed || cfgLsp.getPathStatus() != PathStatus.Sync) {
252 /* Loop the path description to add reserved bandwidth and triggers for this LSP */
253 final Long bw = cts.getBandwidth() == null ? 0L : cts.getBandwidth().getValue().longValue();
254 int cos = cts.getClassType() == null ? 0 : cts.getClassType().intValue();
255 final AddressFamily af = cts.getAddressFamily();
256 final String lspId = teNode.getId().getValue() + "/" + cfgLsp.getName();
257 ConnectedEdge edge = null;
258 for (PathDescription path : cpath.getPathDescription()) {
263 if (path.getIpv4() != null) {
264 edge = graph.getConnectedEdge(new IpAddress(path.getIpv4()));
265 } else if (path.getRemoteIpv4() != null) {
266 edge = graph.getConnectedEdge(new IpAddress(path.getRemoteIpv4()));
267 if (edgeAttrNotNull(edge)) {
268 edge = graph.getConnectedEdge(edge.getEdge().getEdgeAttributes().getRemoteAddress());
274 if (path.getIpv6() != null) {
275 edge = graph.getConnectedEdge(new IpAddress(path.getIpv6()));
276 } else if (path.getRemoteIpv6() != null) {
277 edge = graph.getConnectedEdge(new IpAddress(path.getRemoteIpv6()));
278 if (edgeAttrNotNull(edge)) {
279 /* Need to force using IPv6 address as Connected Edge is searched first on IPv4 address */
280 edge = graph.getConnectedEdge(new IpAddress(
281 edge.getEdge().getEdgeAttributes().getRemoteAddress6()));
295 edge.addBandwidth(bw, cos);
297 edge.registerTrigger(this, lspId);
298 if (edge.getSource() != null) {
299 edge.getSource().registerTrigger(this, lspId);
303 edge.delBandwidth(bw, cos);
305 edge.unRegisterTrigger(this, lspId);
306 if (edge.getSource() != null) {
307 edge.getSource().unRegisterTrigger(this, lspId);
311 if (edge != null && edge.getDestination() != null) {
313 edge.getDestination().registerTrigger(this, lspId);
315 edge.getDestination().unRegisterTrigger(this, lspId);
319 /* Finally, reset Trigger Flag to activate them */
323 private boolean edgeAttrNotNull(ConnectedEdge edge) {
324 return edge != null && edge.getEdge() != null && edge.getEdge().getEdgeAttributes() != null;
327 public void setGraph(ConnectedGraph graph) {
328 configureGraph(graph, cfgLsp.getComputedPath(), cfgLsp.getIntendedPath().getConstraints(), true);
331 public void unsetGraph(ConnectedGraph graph) {
332 configureGraph(graph, cfgLsp.getComputedPath(), cfgLsp.getIntendedPath().getConstraints(), false);
335 public void updateGraph(ConnectedGraph graph) {
336 /* First unset Bandwidth and Triggers for the old path if any */
337 if (prevLsp != null) {
338 configureGraph(graph, prevLsp.getComputedPath(), prevLsp.getIntendedPath().getConstraints(), false);
341 /* Then add Bandwidth and Triggers for the current path */
342 configureGraph(graph, cfgLsp.getComputedPath(), cfgLsp.getIntendedPath().getConstraints(), true);
344 /* And memorize current LSP for latter update */
349 * Reset Triggered Flag.
351 public void unSetTriggerFlag() {
356 public boolean verifyVertex(@Nullable ConnectedVertex next, @Nullable Vertex current) {
357 /* Check if there is an on-going trigger */
362 /* Check if Vertex has been removed */
363 Vertex vertex = next.getVertex();
364 if (vertex == null) {
369 /* Check if Vertex changed its Segment Routing Global Block */
370 final AddressFamily af = cfgLsp.getIntendedPath().getConstraints().getAddressFamily();
371 if ((af == AddressFamily.SrIpv4 || af == AddressFamily.SrIpv6) && !current.getSrgb().equals(vertex.getSrgb())) {
372 LOG.debug("Vertex {} modified its SRGB {} / {}", vertex.getName(), current.getSrgb(), vertex.getSrgb());
383 public boolean verifyEdge(@Nullable ConnectedEdge next, @Nullable Edge current) {
384 /* Check if there is an on-going trigger */
389 /* Check if Edge or Attributes has been removed */
390 Edge edge = next.getEdge();
391 if (edge == null || edge.getEdgeAttributes() == null) {
396 /* Check that Configured LSP has valid constraints */
397 final Constraints constraints = cfgLsp.getIntendedPath().getConstraints();
398 if (constraints == null) {
402 /* Check if Metric is always met */
405 if (constraints.getDelay() != null) {
406 if (edge.getEdgeAttributes().getDelay() != null) {
407 metric = constraints.getDelay().getValue().longValue();
408 delta = edge.getEdgeAttributes().getDelay().getValue().longValue()
409 - current.getEdgeAttributes().getDelay().getValue().longValue();
415 if (constraints.getTeMetric() != null) {
416 if (edge.getEdgeAttributes().getTeMetric() != null) {
417 metric = constraints.getTeMetric().longValue();
418 delta = edge.getEdgeAttributes().getTeMetric().longValue()
419 - current.getEdgeAttributes().getTeMetric().longValue();
424 } else if (constraints.getMetric() != null) {
425 if (edge.getEdgeAttributes().getMetric() != null) {
426 metric = constraints.getMetric().longValue();
427 delta = edge.getEdgeAttributes().getMetric().longValue()
428 - current.getEdgeAttributes().getMetric().longValue();
434 if (metric != 0L && cfgLsp.getComputedPath().getComputedMetric() != null
435 && cfgLsp.getComputedPath().getComputedMetric().longValue() + delta > metric) {
436 LOG.debug("Following an update on Edge {} Metric is no longer guaranteed: {} / {}",
438 cfgLsp.getComputedPath().getComputedMetric().longValue() + delta,
444 /* Check if Bandwidth is always met */
445 if (constraints.getBandwidth() != null) {
446 if (edge.getEdgeAttributes().getMaxLinkBandwidth() == null
447 || edge.getEdgeAttributes().getMaxResvLinkBandwidth() == null
448 || edge.getEdgeAttributes().getUnreservedBandwidth() == null) {
452 Long bandwidth = constraints.getBandwidth().getValue().longValue();
455 for (UnreservedBandwidth unResBw : edge.getEdgeAttributes().getUnreservedBandwidth()) {
456 if (unResBw.getClassType().intValue() == cos) {
457 unrsv = unResBw.getBandwidth().getValue().longValue();
461 Long maxBW = edge.getEdgeAttributes().getMaxLinkBandwidth().getValue().longValue();
462 if (bandwidth > List.of(
464 /* maxBW might be on the list but will always be greater than the next items */
465 maxBW - next.getCosResvBandwidth(cos),
466 maxBW - next.getGlobalResvBandwidth(),
467 edge.getEdgeAttributes().getMaxResvLinkBandwidth().getValue().longValue())
468 .stream().mapToLong(v -> v)
471 LOG.debug("Following an update on Edge {}, Reserved bandwidth is no longer guaranteed", edge.getName());
477 /* Check if Edge changed its Adjacency SID */
478 final AddressFamily af = cfgLsp.getIntendedPath().getConstraints().getAddressFamily();
479 if ((af == AddressFamily.SrIpv4 || af == AddressFamily.SrIpv6)
480 && !current.getEdgeAttributes().getAdjSid().equals(edge.getEdgeAttributes().getAdjSid())) {
481 LOG.debug("Edge {} has modified its Adjacency SID", edge.getName());
490 * Convert LSP as Add LSP Input class to enforce it into the PCC through a call to add-lsp RPCs.
492 * @return new Add LSP Input
494 private AddLspInput getAddLspInput() {
495 /* Create EndPoint Object */
496 final IntendedPath iPath = cfgLsp.getIntendedPath();
497 final EndpointsObjBuilder epb = new EndpointsObjBuilder()
499 .setProcessingRule(true);
500 if (iPath.getSource().getIpv4Address() != null) {
501 final Ipv4Builder ipBuilder = new Ipv4Builder()
502 .setDestinationIpv4Address(new Ipv4AddressNoZone(iPath.getDestination().getIpv4Address()))
503 .setSourceIpv4Address(new Ipv4AddressNoZone(iPath.getSource().getIpv4Address()));
504 epb.setAddressFamily((new Ipv4CaseBuilder().setIpv4(ipBuilder.build()).build()));
505 } else if (cfgLsp.getIntendedPath().getSource().getIpv6Address() != null) {
506 final Ipv6Builder ipBuilder = new Ipv6Builder()
507 .setDestinationIpv6Address(new Ipv6AddressNoZone(iPath.getDestination().getIpv6Address()))
508 .setSourceIpv6Address(new Ipv6AddressNoZone(iPath.getSource().getIpv6Address()));
509 epb.setAddressFamily((new Ipv6CaseBuilder().setIpv6(ipBuilder.build()).build()));
515 /* Create Path Setup Type */
516 final PathSetupTypeBuilder pstBuilder = new PathSetupTypeBuilder();
517 switch (iPath.getConstraints().getAddressFamily()) {
520 pstBuilder.setPst(Uint8.ONE);
523 pstBuilder.setPst(Uint8.ZERO);
528 final LspBuilder lspBuilder = new LspBuilder()
529 .setAdministrative(true)
532 /* Build Arguments. */
533 final ArgumentsBuilder args = new ArgumentsBuilder()
534 .setEndpointsObj(epb.build())
535 .setEro(MessagesUtil.getEro(cfgLsp.getComputedPath().getPathDescription()))
536 .addAugmentation(new Arguments2Builder()
537 .setLsp(lspBuilder.build())
538 .setPathSetupType(pstBuilder.build())
541 /* with Bandwidth and Metric if defined */
542 if (iPath.getConstraints().getBandwidth() != null) {
543 final int ftoi = Float.floatToIntBits(iPath.getConstraints().getBandwidth().getValue().floatValue());
544 final byte[] itob = { (byte) (0xFF & ftoi >> 24), (byte) (0xFF & ftoi >> 16), (byte) (0xFF & ftoi >> 8),
545 (byte) (0xFF & ftoi) };
546 args.setBandwidth(new BandwidthBuilder().setBandwidth(new Bandwidth(itob)).build());
548 /* Note that Delay are not set because, at least, Juniper Routers don't support them */
549 if (iPath.getConstraints().getTeMetric() != null) {
550 final MetricBuilder metricBuilder = new MetricBuilder()
552 .setMetricType(Uint8.TWO)
553 .setValue(new Float32(ByteBuffer.allocate(4)
554 .putFloat(iPath.getConstraints().getTeMetric().floatValue()).array()));
555 args.setMetrics(Collections.singletonList(new MetricsBuilder().setMetric(metricBuilder.build()).build()));
556 } else if (iPath.getConstraints().getMetric() != null) {
557 final MetricBuilder metricBuilder = new MetricBuilder()
559 .setMetricType(Uint8.ONE)
560 .setValue(new Float32(
561 ByteBuffer.allocate(4).putFloat(iPath.getConstraints().getMetric().floatValue()).array()));
562 args.setMetrics(Collections.singletonList(new MetricsBuilder().setMetric(metricBuilder.build()).build()));
566 * NOTE: Seems that ClassType is not supported by some routers. Skip it for the moment.
568 /* With Class Type if defined
569 if (iPath.getConstraints().getClassType() != null) {
571 new ClassTypeBuilder()
572 .setClassType(new ClassType(iPath.getConstraints().getClassType()))
574 .setProcessingRule(true)
579 /* Finally, build addLSP input */
580 return new AddLspInputBuilder()
581 .setNode(teNode.getId())
582 .setName(cfgLsp.getName())
583 .setArguments(args.build())
584 .setNetworkTopologyRef(new NetworkTopologyRef(pcepTopology))
590 * Call add-lsp RPC to enforce the LSP into the PCC. This action will trigger a PcInitiate message to the PCC.
592 * @param addLsp Add Lsp RPC
594 * @return Add LSP Output to convey the RPC result
596 public ListenableFuture<RpcResult<AddLspOutput>> addPath(final AddLsp addLsp) {
597 /* Check if we could add this path */
598 if ((type != PathType.Initiated) || !teNode.isSync()) {
602 /* Check if we have a valid Path */
603 if (cfgLsp.getComputedPath().getComputationStatus() != ComputationStatus.Completed) {
608 final ListenableFuture<RpcResult<AddLspOutput>> enforce = addLsp.invoke(getAddLspInput());
609 LOG.info("Call Add LSP to {} with {}", addLsp, enforce);
610 Futures.addCallback(enforce, new FutureCallback<RpcResult<AddLspOutput>>() {
612 public void onSuccess(final RpcResult<AddLspOutput> result) {
613 if (result.isSuccessful()) {
614 LOG.debug("Enforce LSP success {}", result.getResult());
616 LOG.debug("Unable to enforce LSP {} on Node {}: Got error {}", cfgLsp.getName(), teNode.getId(),
623 public void onFailure(final Throwable throwable) {
624 LOG.warn("Failed enforce LSP {} on Node {}", cfgLsp.getName(), teNode.getId());
627 }, MoreExecutors.directExecutor());
633 * Convert LSP as Update LSP Input class to update it into the PCC through a call to update-lsp RPCs.
635 * @return new Update LSP Input
637 private UpdateLspInput getUpdateLspInput() {
638 /* Create Path Setup Type */
639 final IntendedPath iPath = cfgLsp.getIntendedPath();
640 final PathSetupTypeBuilder pstBuilder = new PathSetupTypeBuilder();
641 switch (iPath.getConstraints().getAddressFamily()) {
644 pstBuilder.setPst(Uint8.ONE);
647 pstBuilder.setPst(Uint8.ZERO);
652 final LspBuilder lspBuilder = new LspBuilder()
653 .setAdministrative(true)
656 /* Build Arguments */
657 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730
658 .update.lsp.args.ArgumentsBuilder args;
659 args = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730
660 .update.lsp.args.ArgumentsBuilder()
661 .addAugmentation(new Arguments3Builder()
662 .setLsp(lspBuilder.build())
663 .setPathSetupType(pstBuilder.build())
665 .setEro(MessagesUtil.getEro(cfgLsp.getComputedPath().getPathDescription()));
667 /* with Bandwidth and Metric if defined */
668 if (iPath.getConstraints().getBandwidth() != null) {
669 final int ftoi = Float.floatToIntBits(iPath.getConstraints().getBandwidth().getValue().floatValue());
670 final byte[] itob = { (byte) (0xFF & ftoi >> 24), (byte) (0xFF & ftoi >> 16), (byte) (0xFF & ftoi >> 8),
671 (byte) (0xFF & ftoi) };
672 args.setBandwidth(new BandwidthBuilder().setBandwidth(new Bandwidth(itob)).build());
674 /* Note that Delay are not set because, at least, Juniper Routers don't support them */
675 if (iPath.getConstraints().getTeMetric() != null) {
676 final MetricBuilder metricBuilder = new MetricBuilder()
678 .setMetricType(Uint8.TWO)
679 .setValue(new Float32(ByteBuffer.allocate(4)
680 .putFloat(iPath.getConstraints().getTeMetric().floatValue()).array()));
681 args.setMetrics(Collections.singletonList(new MetricsBuilder().setMetric(metricBuilder.build()).build()));
682 } else if (iPath.getConstraints().getMetric() != null) {
683 final MetricBuilder metricBuilder = new MetricBuilder()
685 .setMetricType(Uint8.ONE)
686 .setValue(new Float32(ByteBuffer.allocate(4)
687 .putFloat(iPath.getConstraints().getMetric().floatValue()).array()));
688 args.setMetrics(Collections.singletonList(new MetricsBuilder().setMetric(metricBuilder.build()).build()));
692 * NOTE: Seems that ClassType is not supported by some routers. Skip it for the moment.
694 /* With Class Type if defined
695 if (iPath.getConstraints().getClassType() != null) {
697 new ClassTypeBuilder()
698 .setClassType(new ClassType(iPath.getConstraints().getClassType()))
700 .setProcessingRule(true)
705 /* Finally, build updateLSP input */
706 return new UpdateLspInputBuilder()
707 .setNode(teNode.getId())
708 .setName(cfgLsp.getName())
709 .setArguments(args.build())
710 .setNetworkTopologyRef(new NetworkTopologyRef(pcepTopology))
715 * Call update-lsp RPC to enforce the LSP into the PCC. This action will trigger a PcUpdate message to the PCC.
717 * @param updateLsp Update LSP RPC
719 * @return Update LSP Output to convey the RPC result
721 public ListenableFuture<RpcResult<UpdateLspOutput>> updatePath(final UpdateLsp updateLsp) {
723 /* Check if we could update this path */
724 if ((type != PathType.Initiated && type != PathType.Delegated) || !teNode.isSync()) {
728 /* Check if we have a valid ERO */
729 if (cfgLsp.getComputedPath().getComputationStatus() != ComputationStatus.Completed) {
734 final NodeId id = teNode.getId();
735 final ListenableFuture<RpcResult<UpdateLspOutput>> enforce = updateLsp.invoke(getUpdateLspInput());
736 LOG.info("Call Update LSP to {} with {}", updateLsp, enforce);
737 Futures.addCallback(enforce, new FutureCallback<RpcResult<UpdateLspOutput>>() {
739 public void onSuccess(final RpcResult<UpdateLspOutput> result) {
740 if (result.isSuccessful()) {
741 LOG.debug("Update LSP success {}", result.getResult());
743 LOG.debug("Unable to update LSP {} on Node {}: Got error {}", cfgLsp.getName(), id,
750 public void onFailure(final Throwable throwable) {
751 LOG.warn("Failed update LSP {} on Node {}", cfgLsp.getName(), id);
754 }, MoreExecutors.directExecutor());
760 * Call remove-lsp RPC to remove the LSP from the PCC. This action will trigger a PcInitiate message to the PCC
763 * @param removeLsp Remove Lsp RPC
765 * @return Remove LSP Output to convey the RPC result
767 public ListenableFuture<RpcResult<RemoveLspOutput>> removePath(final RemoveLsp removeLsp) {
769 /* Check if we could remove this path */
770 if ((type != PathType.Initiated) || !teNode.isSync() || cfgLsp.getPathStatus() != PathStatus.Sync) {
775 final NodeId id = teNode.getId();
776 final RemoveLspInput rli = new RemoveLspInputBuilder()
778 .setName(cfgLsp.getName())
779 .setNetworkTopologyRef(new NetworkTopologyRef(pcepTopology))
781 final ListenableFuture<RpcResult<RemoveLspOutput>> enforce = removeLsp.invoke(rli);
782 LOG.info("Call Remove LSP to {} with {}", removeLsp, enforce);
783 Futures.addCallback(enforce, new FutureCallback<RpcResult<RemoveLspOutput>>() {
785 public void onSuccess(final RpcResult<RemoveLspOutput> result) {
786 if (result.isSuccessful()) {
787 LOG.debug("Delete LSP success {}", result.getResult());
789 LOG.debug("Unable to delete LSP {} on Node {}: Got error {}", cfgLsp.getName(), id,
796 public void onFailure(final Throwable throwable) {
797 LOG.warn("Failed delete LSP {} on Node {}", cfgLsp.getName(), id);
800 }, MoreExecutors.directExecutor());
806 * Add LSP components to the Operational Data Store.
808 public synchronized void addToDataStore() {
809 /* Check if we could add this path */
810 if (!teNode.isSync()) {
814 final WriteTransaction trans = teNode.getTransaction();
815 trans.put(LogicalDatastoreType.OPERATIONAL, pccIdentifier.child(ConfiguredLsp.class, cfgLsp.key()), cfgLsp);
816 trans.commit().addCallback(new FutureCallback<CommitInfo>() {
818 public void onSuccess(final CommitInfo result) {
819 LOG.debug("Configured LSP {} has been published in operational datastore ", cfgLsp.getName());
823 public void onFailure(final Throwable throwable) {
824 LOG.error("Cannot write Configured LSP {} to the operational datastore (transaction: {})",
825 cfgLsp.getName(), trans.getIdentifier());
827 }, MoreExecutors.directExecutor());
831 * Update LSP components to the Data Store.
833 public synchronized void updateToDataStore() {
834 /* Check if we could update this path */
835 if (!teNode.isSync()) {
839 final WriteTransaction trans = teNode.getTransaction();
840 trans.merge(LogicalDatastoreType.OPERATIONAL, pccIdentifier.child(ConfiguredLsp.class, cfgLsp.key()), cfgLsp);
841 trans.commit().addCallback(new FutureCallback<CommitInfo>() {
843 public void onSuccess(final CommitInfo result) {
844 LOG.debug("Configured LSP {} has been updated in operational datastore ", cfgLsp.getName());
848 public void onFailure(final Throwable throwable) {
849 LOG.error("Cannot update Configured LSP {} to the operational datastore (transaction: {})",
850 cfgLsp.getName(), trans.getIdentifier());
852 }, MoreExecutors.directExecutor());
856 * Remove LSP components to the Data Store.
858 public synchronized void removeFromDataStore() {
859 /* Check if we could remove this path */
860 if (!teNode.isSync()) {
864 final WriteTransaction trans = teNode.getTransaction();
865 trans.delete(LogicalDatastoreType.OPERATIONAL, pccIdentifier.child(ConfiguredLsp.class, cfgLsp.key()));
866 trans.commit().addCallback(new FutureCallback<CommitInfo>() {
868 public void onSuccess(final CommitInfo result) {
869 LOG.debug("Configured LSP {} has been deleted in operational datastore ", cfgLsp.getName());
873 public void onFailure(final Throwable throwable) {
874 LOG.error("Cannot delete Configured LSP {} from the operational datastore (transaction: {})",
875 cfgLsp.getName(), trans.getIdentifier());
877 }, MoreExecutors.directExecutor());
881 public String toString() {
882 final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper("ManagedTePath");
883 CodeHelpers.appendValue(helper, "ConfiguredLsp", cfgLsp);
884 CodeHelpers.appendValue(helper, "PathType", type);
885 CodeHelpers.appendValue(helper, "Sent", sent);
886 return helper.toString();