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.NonNull;
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(final ManagedTeNode teNode, final InstanceIdentifier<Topology> topology) {
102 this.teNode = requireNonNull(teNode);
103 pcepTopology = requireNonNull(topology);
104 pccIdentifier = pcepTopology.child(Node.class, new NodeKey(teNode.getId())).augmentation(Node1.class)
105 .child(PathComputationClient.class).augmentation(PathComputationClient1.class);
108 public ManagedTePath(final ManagedTeNode teNode, final ConfiguredLsp lsp,
109 final InstanceIdentifier<Topology> topology) {
110 cfgLsp = requireNonNull(lsp);
111 this.teNode = requireNonNull(teNode);
112 pcepTopology = requireNonNull(topology);
113 pccIdentifier = pcepTopology.child(Node.class, new NodeKey(teNode.getId())).augmentation(Node1.class)
114 .child(PathComputationClient.class).augmentation(PathComputationClient1.class);
117 public ManagedTePath(final ManagedTeNode teNode, final ManagedTePath mngPath) {
118 checkArgument(mngPath != null, "Managed TE Path is mandatory. Can't be null or empty!");
119 cfgLsp = mngPath.getLsp();
120 sent = mngPath.isSent();
121 type = mngPath.getType();
122 this.teNode = requireNonNull(teNode);
123 pcepTopology = mngPath.getTopology();
124 pccIdentifier = pcepTopology.child(Node.class, new NodeKey(teNode.getId())).augmentation(Node1.class)
125 .child(PathComputationClient.class).augmentation(PathComputationClient1.class);
128 public ConfiguredLsp getLsp() {
132 public ManagedTeNode getManagedTeNode() {
136 public PathType getType() {
140 public InstanceIdentifier<Topology> getTopology() {
144 public ManagedTePath setConfiguredLsp(final ConfiguredLsp lsp) {
150 public ManagedTePath setType(final PathType type) {
156 * Mark this TE Path as synchronized and update the Data Store accordingly.
160 cfgLsp = new ConfiguredLspBuilder(cfgLsp).setPathStatus(PathStatus.Sync).build();
165 * Disabling this TE Path by marking it as Configured. Do not update the Data Store.
167 public void disabled() {
168 cfgLsp = new ConfiguredLspBuilder(cfgLsp).setPathStatus(PathStatus.Configured).build();
172 * Mark this TE Path as Failed.
174 public void failed() {
175 cfgLsp = new ConfiguredLspBuilder(cfgLsp).setPathStatus(PathStatus.Failed).build();
179 public boolean isSent() {
184 * Compare the current TE Path against the reported LSP to determine if there are in Sync, need Update or
185 * considered as in Failure if already updated.
187 * @param lsp LSP that corresponds to the reported LSP
189 * @return new LSP status
191 public PathStatus checkReportedPath(final ConfiguredLsp lsp) {
192 /* Check if this path has not been already verified */
193 if (cfgLsp.getPathStatus() == PathStatus.Sync) {
194 return PathStatus.Sync;
197 /* Check Source, Destination and routing method which must be the same */
198 final IntendedPath iPath = lsp.getIntendedPath();
199 final IntendedPath rPath = lsp.getIntendedPath();
200 PathStatus newStatus = sent ? PathStatus.Failed : PathStatus.Updated;
201 if (!iPath.getSource().equals(rPath.getSource()) || !iPath.getDestination().equals(rPath.getDestination())) {
202 return PathStatus.Failed;
205 /* Check constraints ... */
206 final Constraints icts = iPath.getConstraints();
207 final Constraints rcts = rPath.getConstraints();
208 if (!icts.getAddressFamily().equals(rcts.getAddressFamily())) {
211 if (icts.getBandwidth() != null && !icts.getBandwidth().equals(rcts.getBandwidth())) {
215 * ClassType, TE metric and Delay are not supported by all routers: need
216 * to check them only if there are all present
218 if (icts.getClassType() != null && rcts.getClassType() != null
219 && !icts.getClassType().equals(rcts.getClassType())) {
222 if (icts.getTeMetric() != null && rcts.getTeMetric() != null
223 && !icts.getTeMetric().equals(rcts.getTeMetric())) {
226 if (icts.getDelay() != null && rcts.getDelay() != null && !icts.getDelay().equals(rcts.getDelay())) {
230 /* ... and Path to determine if an update is required */
231 if (lsp.getComputedPath().getComputationStatus() != ComputationStatus.Completed) {
232 return PathStatus.Failed;
234 if (!lsp.getComputedPath().getPathDescription().equals(lsp.getComputedPath().getPathDescription())) {
238 /* All is conform. LSP is in sync with expected result. */
239 return PathStatus.Sync;
242 private void configureGraph(final ConnectedGraph graph, final ComputedPath cpath, final Constraints cts,
243 final boolean config) {
244 /* Check that Connected Graph is valid */
249 /* Verify that we have a valid Computed Path and that the LSP is in SYNC */
250 if (cpath.getComputationStatus() != ComputationStatus.Completed || cfgLsp.getPathStatus() != PathStatus.Sync) {
254 /* Loop the path description to add reserved bandwidth and triggers for this LSP */
255 final Long bw = cts.getBandwidth() == null ? 0L : cts.getBandwidth().getValue().longValue();
256 int cos = cts.getClassType() == null ? 0 : cts.getClassType().intValue();
257 final AddressFamily af = cts.getAddressFamily();
258 final String lspId = teNode.getId().getValue() + "/" + cfgLsp.getName();
259 ConnectedEdge edge = null;
260 for (PathDescription path : cpath.getPathDescription()) {
265 if (path.getIpv4() != null) {
266 edge = graph.getConnectedEdge(new IpAddress(path.getIpv4()));
267 } else if (path.getRemoteIpv4() != null) {
268 edge = graph.getConnectedEdge(new IpAddress(path.getRemoteIpv4()));
269 if (edgeAttrNotNull(edge)) {
270 edge = graph.getConnectedEdge(edge.getEdge().getEdgeAttributes().getRemoteAddress());
276 if (path.getIpv6() != null) {
277 edge = graph.getConnectedEdge(new IpAddress(path.getIpv6()));
278 } else if (path.getRemoteIpv6() != null) {
279 edge = graph.getConnectedEdge(new IpAddress(path.getRemoteIpv6()));
280 if (edgeAttrNotNull(edge)) {
281 /* Need to force using IPv6 address as Connected Edge is searched first on IPv4 address */
282 edge = graph.getConnectedEdge(new IpAddress(
283 edge.getEdge().getEdgeAttributes().getRemoteAddress6()));
297 edge.addBandwidth(bw, cos);
299 edge.registerTrigger(this, lspId);
300 if (edge.getSource() != null) {
301 edge.getSource().registerTrigger(this, lspId);
305 edge.delBandwidth(bw, cos);
307 edge.unRegisterTrigger(this, lspId);
308 if (edge.getSource() != null) {
309 edge.getSource().unRegisterTrigger(this, lspId);
313 if (edge != null && edge.getDestination() != null) {
315 edge.getDestination().registerTrigger(this, lspId);
317 edge.getDestination().unRegisterTrigger(this, lspId);
321 /* Finally, reset Trigger Flag to activate them */
325 private static boolean edgeAttrNotNull(final ConnectedEdge edge) {
326 return edge != null && edge.getEdge() != null && edge.getEdge().getEdgeAttributes() != null;
329 public void setGraph(final ConnectedGraph graph) {
330 configureGraph(graph, cfgLsp.getComputedPath(), cfgLsp.getIntendedPath().getConstraints(), true);
333 public void unsetGraph(final ConnectedGraph graph) {
334 configureGraph(graph, cfgLsp.getComputedPath(), cfgLsp.getIntendedPath().getConstraints(), false);
337 public void updateGraph(final ConnectedGraph graph) {
338 /* First unset Bandwidth and Triggers for the old path if any */
339 if (prevLsp != null) {
340 configureGraph(graph, prevLsp.getComputedPath(), prevLsp.getIntendedPath().getConstraints(), false);
343 /* Then add Bandwidth and Triggers for the current path */
344 configureGraph(graph, cfgLsp.getComputedPath(), cfgLsp.getIntendedPath().getConstraints(), true);
346 /* And memorize current LSP for latter update */
351 * Reset Triggered Flag.
353 public void unSetTriggerFlag() {
358 public boolean verifyVertex(final ConnectedVertex next, final Vertex current) {
359 /* Check if there is an on-going trigger */
364 /* Check if Vertex has been removed */
365 Vertex vertex = next.getVertex();
366 if (vertex == null) {
371 /* Check if Vertex changed its Segment Routing Global Block */
372 final AddressFamily af = cfgLsp.getIntendedPath().getConstraints().getAddressFamily();
373 if ((af == AddressFamily.SrIpv4 || af == AddressFamily.SrIpv6) && !current.getSrgb().equals(vertex.getSrgb())) {
374 LOG.debug("Vertex {} modified its SRGB {} / {}", vertex.getName(), current.getSrgb(), vertex.getSrgb());
385 public boolean verifyEdge(final ConnectedEdge next, final Edge current) {
386 /* Check if there is an on-going trigger */
391 /* Check if Edge or Attributes has been removed */
392 Edge edge = next.getEdge();
393 if (edge == null || edge.getEdgeAttributes() == null) {
398 /* Check that Configured LSP has valid constraints */
399 final Constraints constraints = cfgLsp.getIntendedPath().getConstraints();
400 if (constraints == null) {
404 /* Check if Metric is always met */
407 if (constraints.getDelay() != null) {
408 if (edge.getEdgeAttributes().getDelay() != null) {
409 metric = constraints.getDelay().getValue().longValue();
410 delta = edge.getEdgeAttributes().getDelay().getValue().longValue()
411 - current.getEdgeAttributes().getDelay().getValue().longValue();
417 if (constraints.getTeMetric() != null) {
418 if (edge.getEdgeAttributes().getTeMetric() != null) {
419 metric = constraints.getTeMetric().longValue();
420 delta = edge.getEdgeAttributes().getTeMetric().longValue()
421 - current.getEdgeAttributes().getTeMetric().longValue();
426 } else if (constraints.getMetric() != null) {
427 if (edge.getEdgeAttributes().getMetric() != null) {
428 metric = constraints.getMetric().longValue();
429 delta = edge.getEdgeAttributes().getMetric().longValue()
430 - current.getEdgeAttributes().getMetric().longValue();
436 if (metric != 0L && cfgLsp.getComputedPath().getComputedMetric() != null
437 && cfgLsp.getComputedPath().getComputedMetric().longValue() + delta > metric) {
438 LOG.debug("Following an update on Edge {} Metric is no longer guaranteed: {} / {}",
440 cfgLsp.getComputedPath().getComputedMetric().longValue() + delta,
446 /* Check if Bandwidth is always met */
447 if (constraints.getBandwidth() != null) {
448 if (edge.getEdgeAttributes().getMaxLinkBandwidth() == null
449 || edge.getEdgeAttributes().getMaxResvLinkBandwidth() == null
450 || edge.getEdgeAttributes().getUnreservedBandwidth() == null) {
454 Long bandwidth = constraints.getBandwidth().getValue().longValue();
457 for (UnreservedBandwidth unResBw : edge.getEdgeAttributes().getUnreservedBandwidth()) {
458 if (unResBw.getClassType().intValue() == cos) {
459 unrsv = unResBw.getBandwidth().getValue().longValue();
463 Long maxBW = edge.getEdgeAttributes().getMaxLinkBandwidth().getValue().longValue();
464 if (bandwidth > List.of(
466 /* maxBW might be on the list but will always be greater than the next items */
467 maxBW - next.getCosResvBandwidth(cos),
468 maxBW - next.getGlobalResvBandwidth(),
469 edge.getEdgeAttributes().getMaxResvLinkBandwidth().getValue().longValue())
470 .stream().mapToLong(v -> v)
473 LOG.debug("Following an update on Edge {}, Reserved bandwidth is no longer guaranteed", edge.getName());
479 /* Check if Edge changed its Adjacency SID */
480 final AddressFamily af = cfgLsp.getIntendedPath().getConstraints().getAddressFamily();
481 if ((af == AddressFamily.SrIpv4 || af == AddressFamily.SrIpv6)
482 && !current.getEdgeAttributes().getAdjSid().equals(edge.getEdgeAttributes().getAdjSid())) {
483 LOG.debug("Edge {} has modified its Adjacency SID", edge.getName());
492 * Convert LSP as Add LSP Input class to enforce it into the PCC through a call to add-lsp RPCs.
494 * @return new Add LSP Input
496 private AddLspInput getAddLspInput() {
497 /* Create EndPoint Object */
498 final IntendedPath iPath = cfgLsp.getIntendedPath();
499 final EndpointsObjBuilder epb = new EndpointsObjBuilder()
501 .setProcessingRule(true);
502 if (iPath.getSource().getIpv4Address() != null) {
503 final Ipv4Builder ipBuilder = new Ipv4Builder()
504 .setDestinationIpv4Address(new Ipv4AddressNoZone(iPath.getDestination().getIpv4Address()))
505 .setSourceIpv4Address(new Ipv4AddressNoZone(iPath.getSource().getIpv4Address()));
506 epb.setAddressFamily(new Ipv4CaseBuilder().setIpv4(ipBuilder.build()).build());
507 } else if (cfgLsp.getIntendedPath().getSource().getIpv6Address() != null) {
508 final Ipv6Builder ipBuilder = new Ipv6Builder()
509 .setDestinationIpv6Address(new Ipv6AddressNoZone(iPath.getDestination().getIpv6Address()))
510 .setSourceIpv6Address(new Ipv6AddressNoZone(iPath.getSource().getIpv6Address()));
511 epb.setAddressFamily(new Ipv6CaseBuilder().setIpv6(ipBuilder.build()).build());
517 /* Create Path Setup Type */
518 final PathSetupTypeBuilder pstBuilder = new PathSetupTypeBuilder();
519 switch (iPath.getConstraints().getAddressFamily()) {
522 pstBuilder.setPst(Uint8.ONE);
525 pstBuilder.setPst(Uint8.ZERO);
530 final LspBuilder lspBuilder = new LspBuilder()
531 .setAdministrative(true)
534 /* Build Arguments. */
535 final ArgumentsBuilder args = new ArgumentsBuilder()
536 .setEndpointsObj(epb.build())
537 .setEro(MessagesUtil.getEro(cfgLsp.getComputedPath().getPathDescription()))
538 .addAugmentation(new Arguments2Builder()
539 .setLsp(lspBuilder.build())
540 .setPathSetupType(pstBuilder.build())
543 /* with Bandwidth and Metric if defined */
544 if (iPath.getConstraints().getBandwidth() != null) {
545 final int ftoi = Float.floatToIntBits(iPath.getConstraints().getBandwidth().getValue().floatValue());
546 final byte[] itob = { (byte) (0xFF & ftoi >> 24), (byte) (0xFF & ftoi >> 16), (byte) (0xFF & ftoi >> 8),
547 (byte) (0xFF & ftoi) };
548 args.setBandwidth(new BandwidthBuilder().setBandwidth(new Bandwidth(itob)).build());
550 /* Note that Delay are not set because, at least, Juniper Routers don't support them */
551 if (iPath.getConstraints().getTeMetric() != null) {
552 final MetricBuilder metricBuilder = new MetricBuilder()
554 .setMetricType(Uint8.TWO)
555 .setValue(new Float32(ByteBuffer.allocate(4)
556 .putFloat(iPath.getConstraints().getTeMetric().floatValue()).array()));
557 args.setMetrics(Collections.singletonList(new MetricsBuilder().setMetric(metricBuilder.build()).build()));
558 } else if (iPath.getConstraints().getMetric() != null) {
559 final MetricBuilder metricBuilder = new MetricBuilder()
561 .setMetricType(Uint8.ONE)
562 .setValue(new Float32(
563 ByteBuffer.allocate(4).putFloat(iPath.getConstraints().getMetric().floatValue()).array()));
564 args.setMetrics(Collections.singletonList(new MetricsBuilder().setMetric(metricBuilder.build()).build()));
568 * NOTE: Seems that ClassType is not supported by some routers. Skip it for the moment.
570 /* With Class Type if defined
571 if (iPath.getConstraints().getClassType() != null) {
573 new ClassTypeBuilder()
574 .setClassType(new ClassType(iPath.getConstraints().getClassType()))
576 .setProcessingRule(true)
581 /* Finally, build addLSP input */
582 return new AddLspInputBuilder()
583 .setNode(teNode.getId())
584 .setName(cfgLsp.getName())
585 .setArguments(args.build())
586 .setNetworkTopologyRef(new NetworkTopologyRef(pcepTopology))
592 * Call add-lsp RPC to enforce the LSP into the PCC. This action will trigger a PcInitiate message to the PCC.
594 * @param addLsp Add Lsp RPC
596 * @return Add LSP Output to convey the RPC result
598 public ListenableFuture<RpcResult<AddLspOutput>> addPath(final AddLsp addLsp) {
599 /* Check if we could add this path */
600 if (type != PathType.Initiated || !teNode.isSync()) {
604 /* Check if we have a valid Path */
605 if (cfgLsp.getComputedPath().getComputationStatus() != ComputationStatus.Completed) {
610 final var enforce = addLsp.invoke(getAddLspInput());
611 LOG.info("Call Add LSP to {} with {}", addLsp, enforce);
612 Futures.addCallback(enforce, new FutureCallback<>() {
614 public void onSuccess(final RpcResult<AddLspOutput> result) {
615 if (result.isSuccessful()) {
616 LOG.debug("Enforce LSP success {}", result.getResult());
618 LOG.debug("Unable to enforce LSP {} on Node {}: Got error {}", cfgLsp.getName(), teNode.getId(),
625 public void onFailure(final Throwable throwable) {
626 LOG.warn("Failed enforce LSP {} on Node {}", cfgLsp.getName(), teNode.getId());
629 }, MoreExecutors.directExecutor());
635 * Convert LSP as Update LSP Input class to update it into the PCC through a call to update-lsp RPCs.
637 * @return new Update LSP Input
639 private @NonNull UpdateLspInput getUpdateLspInput() {
640 /* Create Path Setup Type */
641 final IntendedPath iPath = cfgLsp.getIntendedPath();
642 final PathSetupTypeBuilder pstBuilder = new PathSetupTypeBuilder();
643 switch (iPath.getConstraints().getAddressFamily()) {
646 pstBuilder.setPst(Uint8.ONE);
649 pstBuilder.setPst(Uint8.ZERO);
654 final LspBuilder lspBuilder = new LspBuilder()
655 .setAdministrative(true)
658 /* Build Arguments */
659 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730
660 .update.lsp.args.ArgumentsBuilder args;
661 args = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730
662 .update.lsp.args.ArgumentsBuilder()
663 .addAugmentation(new Arguments3Builder()
664 .setLsp(lspBuilder.build())
665 .setPathSetupType(pstBuilder.build())
667 .setEro(MessagesUtil.getEro(cfgLsp.getComputedPath().getPathDescription()));
669 /* with Bandwidth and Metric if defined */
670 if (iPath.getConstraints().getBandwidth() != null) {
671 final int ftoi = Float.floatToIntBits(iPath.getConstraints().getBandwidth().getValue().floatValue());
672 final byte[] itob = { (byte) (0xFF & ftoi >> 24), (byte) (0xFF & ftoi >> 16), (byte) (0xFF & ftoi >> 8),
673 (byte) (0xFF & ftoi) };
674 args.setBandwidth(new BandwidthBuilder().setBandwidth(new Bandwidth(itob)).build());
676 /* Note that Delay are not set because, at least, Juniper Routers don't support them */
677 if (iPath.getConstraints().getTeMetric() != null) {
678 final MetricBuilder metricBuilder = new MetricBuilder()
680 .setMetricType(Uint8.TWO)
681 .setValue(new Float32(ByteBuffer.allocate(4)
682 .putFloat(iPath.getConstraints().getTeMetric().floatValue()).array()));
683 args.setMetrics(Collections.singletonList(new MetricsBuilder().setMetric(metricBuilder.build()).build()));
684 } else if (iPath.getConstraints().getMetric() != null) {
685 final MetricBuilder metricBuilder = new MetricBuilder()
687 .setMetricType(Uint8.ONE)
688 .setValue(new Float32(ByteBuffer.allocate(4)
689 .putFloat(iPath.getConstraints().getMetric().floatValue()).array()));
690 args.setMetrics(Collections.singletonList(new MetricsBuilder().setMetric(metricBuilder.build()).build()));
694 * NOTE: Seems that ClassType is not supported by some routers. Skip it for the moment.
696 /* With Class Type if defined
697 if (iPath.getConstraints().getClassType() != null) {
699 new ClassTypeBuilder()
700 .setClassType(new ClassType(iPath.getConstraints().getClassType()))
702 .setProcessingRule(true)
707 /* Finally, build updateLSP input */
708 return new UpdateLspInputBuilder()
709 .setNode(teNode.getId())
710 .setName(cfgLsp.getName())
711 .setArguments(args.build())
712 .setNetworkTopologyRef(new NetworkTopologyRef(pcepTopology))
717 * Call update-lsp RPC to enforce the LSP into the PCC. This action will trigger a PcUpdate message to the PCC.
719 * @param updateLsp Update LSP RPC
721 * @return Update LSP Output to convey the RPC result
723 public ListenableFuture<RpcResult<UpdateLspOutput>> updatePath(final UpdateLsp updateLsp) {
725 /* Check if we could update this path */
726 if (type != PathType.Initiated && type != PathType.Delegated || !teNode.isSync()) {
730 /* Check if we have a valid ERO */
731 if (cfgLsp.getComputedPath().getComputationStatus() != ComputationStatus.Completed) {
736 final NodeId id = teNode.getId();
737 final var enforce = updateLsp.invoke(getUpdateLspInput());
738 LOG.info("Call Update LSP to {} with {}", updateLsp, enforce);
739 Futures.addCallback(enforce, new FutureCallback<>() {
741 public void onSuccess(final RpcResult<UpdateLspOutput> result) {
742 if (result.isSuccessful()) {
743 LOG.debug("Update LSP success {}", result.getResult());
745 LOG.debug("Unable to update LSP {} on Node {}: Got error {}", cfgLsp.getName(), id,
752 public void onFailure(final Throwable throwable) {
753 LOG.warn("Failed update LSP {} on Node {}", cfgLsp.getName(), id);
756 }, MoreExecutors.directExecutor());
762 * Call remove-lsp RPC to remove the LSP from the PCC. This action will trigger a PcInitiate message to the PCC
765 * @param removeLsp Remove Lsp RPC
767 * @return Remove LSP Output to convey the RPC result
769 public ListenableFuture<RpcResult<RemoveLspOutput>> removePath(final RemoveLsp removeLsp) {
771 /* Check if we could remove this path */
772 if (type != PathType.Initiated || !teNode.isSync() || cfgLsp.getPathStatus() != PathStatus.Sync) {
777 final NodeId id = teNode.getId();
778 final RemoveLspInput rli = new RemoveLspInputBuilder()
780 .setName(cfgLsp.getName())
781 .setNetworkTopologyRef(new NetworkTopologyRef(pcepTopology))
783 final ListenableFuture<RpcResult<RemoveLspOutput>> enforce = removeLsp.invoke(rli);
784 LOG.info("Call Remove LSP to {} with {}", removeLsp, enforce);
785 Futures.addCallback(enforce, new FutureCallback<RpcResult<RemoveLspOutput>>() {
787 public void onSuccess(final RpcResult<RemoveLspOutput> result) {
788 if (result.isSuccessful()) {
789 LOG.debug("Delete LSP success {}", result.getResult());
791 LOG.debug("Unable to delete LSP {} on Node {}: Got error {}", cfgLsp.getName(), id,
798 public void onFailure(final Throwable throwable) {
799 LOG.warn("Failed delete LSP {} on Node {}", cfgLsp.getName(), id);
802 }, MoreExecutors.directExecutor());
808 * Add LSP components to the Operational Data Store.
810 public synchronized void addToDataStore() {
811 /* Check if we could add this path */
812 if (!teNode.isSync()) {
816 final WriteTransaction trans = teNode.getTransaction();
817 trans.put(LogicalDatastoreType.OPERATIONAL, pccIdentifier.child(ConfiguredLsp.class, cfgLsp.key()), cfgLsp);
818 trans.commit().addCallback(new FutureCallback<CommitInfo>() {
820 public void onSuccess(final CommitInfo result) {
821 LOG.debug("Configured LSP {} has been published in operational datastore ", cfgLsp.getName());
825 public void onFailure(final Throwable throwable) {
826 LOG.error("Cannot write Configured LSP {} to the operational datastore (transaction: {})",
827 cfgLsp.getName(), trans.getIdentifier());
829 }, MoreExecutors.directExecutor());
833 * Update LSP components to the Data Store.
835 public synchronized void updateToDataStore() {
836 /* Check if we could update this path */
837 if (!teNode.isSync()) {
841 final WriteTransaction trans = teNode.getTransaction();
842 trans.merge(LogicalDatastoreType.OPERATIONAL, pccIdentifier.child(ConfiguredLsp.class, cfgLsp.key()), cfgLsp);
843 trans.commit().addCallback(new FutureCallback<CommitInfo>() {
845 public void onSuccess(final CommitInfo result) {
846 LOG.debug("Configured LSP {} has been updated in operational datastore ", cfgLsp.getName());
850 public void onFailure(final Throwable throwable) {
851 LOG.error("Cannot update Configured LSP {} to the operational datastore (transaction: {})",
852 cfgLsp.getName(), trans.getIdentifier());
854 }, MoreExecutors.directExecutor());
858 * Remove LSP components to the Data Store.
860 public synchronized void removeFromDataStore() {
861 /* Check if we could remove this path */
862 if (!teNode.isSync()) {
866 final WriteTransaction trans = teNode.getTransaction();
867 trans.delete(LogicalDatastoreType.OPERATIONAL, pccIdentifier.child(ConfiguredLsp.class, cfgLsp.key()));
868 trans.commit().addCallback(new FutureCallback<CommitInfo>() {
870 public void onSuccess(final CommitInfo result) {
871 LOG.debug("Configured LSP {} has been deleted in operational datastore ", cfgLsp.getName());
875 public void onFailure(final Throwable throwable) {
876 LOG.error("Cannot delete Configured LSP {} from the operational datastore (transaction: {})",
877 cfgLsp.getName(), trans.getIdentifier());
879 }, MoreExecutors.directExecutor());
883 public String toString() {
884 final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper("ManagedTePath");
885 CodeHelpers.appendValue(helper, "ConfiguredLsp", cfgLsp);
886 CodeHelpers.appendValue(helper, "PathType", type);
887 CodeHelpers.appendValue(helper, "Sent", sent);
888 return helper.toString();