import com.google.common.util.concurrent.MoreExecutors;
import java.nio.ByteBuffer;
import java.util.Collections;
+import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.graph.ConnectedEdge;
+import org.opendaylight.graph.ConnectedEdgeTrigger;
import org.opendaylight.graph.ConnectedGraph;
+import org.opendaylight.graph.ConnectedVertex;
+import org.opendaylight.graph.ConnectedVertexTrigger;
import org.opendaylight.mdsal.binding.api.WriteTransaction;
import org.opendaylight.mdsal.common.api.CommitInfo;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
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.Ipv4AddressNoZone;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.Edge;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.Vertex;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.edge.attributes.UnreservedBandwidth;
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.network.topology.rev140113.NetworkTopologyRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev220310.AddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev220310.ComputationStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev220310.path.descriptions.PathDescription;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev220324.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev220324.ComputationStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev220324.path.descriptions.PathDescription;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.Arguments2Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.Arguments3Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.object.LspBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.PathComputationClient1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.PathStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.PathType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.pcc.configured.lsp.ConfiguredLsp;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.pcc.configured.lsp.ConfiguredLspBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.pcc.configured.lsp.configured.lsp.IntendedPath;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.pcc.configured.lsp.configured.lsp.intended.path.Constraints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.PathComputationClient1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.PathStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.PathType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.ConfiguredLsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.ConfiguredLspBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.configured.lsp.ComputedPath;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.configured.lsp.IntendedPath;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.configured.lsp.intended.path.Constraints;
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.endpoints.address.family.Ipv4CaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.address.family.Ipv6CaseBuilder;
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.path.setup.type.tlv.PathSetupTypeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.AddLspInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.AddLspInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.AddLspOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.NetworkTopologyPcepService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.Node1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.RemoveLspInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.RemoveLspInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.RemoveLspOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.UpdateLspInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.UpdateLspInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.UpdateLspOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.add.lsp.args.ArgumentsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.pcep.client.attributes.PathComputationClient;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.AddLsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.AddLspInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.AddLspInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.AddLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.Node1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.RemoveLsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.RemoveLspInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.RemoveLspInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.RemoveLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.UpdateLsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.UpdateLspInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.UpdateLspInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.UpdateLspOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.add.lsp.args.ArgumentsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.pcep.client.attributes.PathComputationClient;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class ManagedTePath {
+public class ManagedTePath implements ConnectedEdgeTrigger, ConnectedVertexTrigger {
private ConfiguredLsp cfgLsp = null;
private ConfiguredLsp prevLsp = null;
private final ManagedTeNode teNode;
private boolean sent = false;
+ private boolean triggerFlag = false;
private PathType type = PathType.Pcc;
private final InstanceIdentifier<Topology> pcepTopology;
private final InstanceIdentifier<PathComputationClient1> pccIdentifier;
private static final Logger LOG = LoggerFactory.getLogger(ManagedTePath.class);
- public ManagedTePath(ManagedTeNode teNode, InstanceIdentifier<Topology> topology) {
+ public ManagedTePath(final ManagedTeNode teNode, final InstanceIdentifier<Topology> topology) {
this.teNode = requireNonNull(teNode);
- this.pcepTopology = requireNonNull(topology);
- this.pccIdentifier = pcepTopology.child(Node.class, new NodeKey(teNode.getId())).augmentation(Node1.class)
+ pcepTopology = requireNonNull(topology);
+ pccIdentifier = pcepTopology.child(Node.class, new NodeKey(teNode.getId())).augmentation(Node1.class)
.child(PathComputationClient.class).augmentation(PathComputationClient1.class);
}
- public ManagedTePath(ManagedTeNode teNode, final ConfiguredLsp lsp, InstanceIdentifier<Topology> topology) {
- this.cfgLsp = requireNonNull(lsp);
+ public ManagedTePath(final ManagedTeNode teNode, final ConfiguredLsp lsp,
+ final InstanceIdentifier<Topology> topology) {
+ cfgLsp = requireNonNull(lsp);
this.teNode = requireNonNull(teNode);
- this.pcepTopology = requireNonNull(topology);
- this.pccIdentifier = pcepTopology.child(Node.class, new NodeKey(teNode.getId())).augmentation(Node1.class)
+ pcepTopology = requireNonNull(topology);
+ pccIdentifier = pcepTopology.child(Node.class, new NodeKey(teNode.getId())).augmentation(Node1.class)
.child(PathComputationClient.class).augmentation(PathComputationClient1.class);
}
- public ManagedTePath(ManagedTeNode teNode, final ManagedTePath mngPath) {
+ public ManagedTePath(final ManagedTeNode teNode, final ManagedTePath mngPath) {
checkArgument(mngPath != null, "Managed TE Path is mandatory. Can't be null or empty!");
- this.cfgLsp = mngPath.getLsp();
- this.sent = mngPath.isSent();
- this.type = mngPath.getType();
+ cfgLsp = mngPath.getLsp();
+ sent = mngPath.isSent();
+ type = mngPath.getType();
this.teNode = requireNonNull(teNode);
- this.pcepTopology = mngPath.getTopology();
- this.pccIdentifier = pcepTopology.child(Node.class, new NodeKey(teNode.getId())).augmentation(Node1.class)
+ pcepTopology = mngPath.getTopology();
+ pccIdentifier = pcepTopology.child(Node.class, new NodeKey(teNode.getId())).augmentation(Node1.class)
.child(PathComputationClient.class).augmentation(PathComputationClient1.class);
}
}
public ManagedTePath setConfiguredLsp(final ConfiguredLsp lsp) {
- this.prevLsp = this.cfgLsp;
- this.cfgLsp = lsp;
+ prevLsp = cfgLsp;
+ cfgLsp = lsp;
return this;
}
- public ManagedTePath setType(PathType type) {
+ public ManagedTePath setType(final PathType type) {
this.type = type;
return this;
}
*
*/
public void sync() {
- this.cfgLsp = new ConfiguredLspBuilder(cfgLsp).setPathStatus(PathStatus.Sync).build();
+ cfgLsp = new ConfiguredLspBuilder(cfgLsp).setPathStatus(PathStatus.Sync).build();
updateToDataStore();
}
* Disabling this TE Path by marking it as Configured. Do not update the Data Store.
*/
public void disabled() {
- this.cfgLsp = new ConfiguredLspBuilder(cfgLsp).setPathStatus(PathStatus.Configured).build();
+ cfgLsp = new ConfiguredLspBuilder(cfgLsp).setPathStatus(PathStatus.Configured).build();
}
/**
* Mark this TE Path as Failed.
*/
public void failed() {
- this.cfgLsp = new ConfiguredLspBuilder(cfgLsp).setPathStatus(PathStatus.Failed).build();
+ cfgLsp = new ConfiguredLspBuilder(cfgLsp).setPathStatus(PathStatus.Failed).build();
updateToDataStore();
}
return PathStatus.Sync;
}
- public void addBandwidth(ConnectedGraph graph) {
+ private void configureGraph(final ConnectedGraph graph, final ComputedPath cpath, final Constraints cts,
+ final boolean config) {
/* Check that Connected Graph is valid */
if (graph == null) {
return;
}
+
/* Verify that we have a valid Computed Path and that the LSP is in SYNC */
- if (cfgLsp.getComputedPath().getComputationStatus() != ComputationStatus.Completed
- || cfgLsp.getPathStatus() != PathStatus.Sync) {
- return;
- }
- /* Verify that a Bandwidth has been requested and reserved */
- if (cfgLsp.getIntendedPath().getConstraints().getBandwidth() == null) {
+ if (cpath.getComputationStatus() != ComputationStatus.Completed || cfgLsp.getPathStatus() != PathStatus.Sync) {
return;
}
- /* Loop the path description to add reserved bandwidth for this LSP */
- final Long bw = cfgLsp.getIntendedPath().getConstraints().getBandwidth().getValue().longValue();
- int cos = cfgLsp.getIntendedPath().getConstraints().getClassType() != null
- ? cfgLsp.getIntendedPath().getConstraints().getClassType().intValue()
- : 0;
- final AddressFamily af = cfgLsp.getIntendedPath().getConstraints().getAddressFamily();
- for (PathDescription path : cfgLsp.getComputedPath().getPathDescription()) {
- ConnectedEdge edge = null;
+ /* Loop the path description to add reserved bandwidth and triggers for this LSP */
+ final Long bw = cts.getBandwidth() == null ? 0L : cts.getBandwidth().getValue().longValue();
+ int cos = cts.getClassType() == null ? 0 : cts.getClassType().intValue();
+ final AddressFamily af = cts.getAddressFamily();
+ final String lspId = teNode.getId().getValue() + "/" + cfgLsp.getName();
+ ConnectedEdge edge = null;
+ for (PathDescription path : cpath.getPathDescription()) {
+ edge = null;
switch (af) {
case Ipv4:
case SrIpv4:
edge = graph.getConnectedEdge(new IpAddress(path.getIpv4()));
} else if (path.getRemoteIpv4() != null) {
edge = graph.getConnectedEdge(new IpAddress(path.getRemoteIpv4()));
- if (edge != null) {
+ if (edgeAttrNotNull(edge)) {
edge = graph.getConnectedEdge(edge.getEdge().getEdgeAttributes().getRemoteAddress());
}
}
edge = graph.getConnectedEdge(new IpAddress(path.getIpv6()));
} else if (path.getRemoteIpv6() != null) {
edge = graph.getConnectedEdge(new IpAddress(path.getRemoteIpv6()));
- if (edge != null) {
+ if (edgeAttrNotNull(edge)) {
/* Need to force using IPv6 address as Connected Edge is searched first on IPv4 address */
edge = graph.getConnectedEdge(new IpAddress(
- edge.getEdge().getEdgeAttributes().getRemoteAddress().getIpv6Address()));
+ edge.getEdge().getEdgeAttributes().getRemoteAddress6()));
}
}
break;
default:
break;
}
- if (edge != null) {
- edge.addBandwidth(bw, cos);
+
+ if (edge == null) {
+ continue;
+ }
+
+ if (config) {
+ if (bw != 0L) {
+ edge.addBandwidth(bw, cos);
+ }
+ edge.registerTrigger(this, lspId);
+ if (edge.getSource() != null) {
+ edge.getSource().registerTrigger(this, lspId);
+ }
+ } else {
+ if (bw != 0L) {
+ edge.delBandwidth(bw, cos);
+ }
+ edge.unRegisterTrigger(this, lspId);
+ if (edge.getSource() != null) {
+ edge.getSource().unRegisterTrigger(this, lspId);
+ }
+ }
+ }
+ if (edge != null && edge.getDestination() != null) {
+ if (config) {
+ edge.getDestination().registerTrigger(this, lspId);
+ } else {
+ edge.getDestination().unRegisterTrigger(this, lspId);
}
}
+
+ /* Finally, reset Trigger Flag to activate them */
+ triggerFlag = false;
}
- public void delBandwidth(ConnectedGraph graph) {
- /* Check that Connected Graph is valid */
- if (graph == null) {
- return;
+ private static boolean edgeAttrNotNull(final ConnectedEdge edge) {
+ return edge != null && edge.getEdge() != null && edge.getEdge().getEdgeAttributes() != null;
+ }
+
+ public void setGraph(final ConnectedGraph graph) {
+ configureGraph(graph, cfgLsp.getComputedPath(), cfgLsp.getIntendedPath().getConstraints(), true);
+ }
+
+ public void unsetGraph(final ConnectedGraph graph) {
+ configureGraph(graph, cfgLsp.getComputedPath(), cfgLsp.getIntendedPath().getConstraints(), false);
+ }
+
+ public void updateGraph(final ConnectedGraph graph) {
+ /* First unset Bandwidth and Triggers for the old path if any */
+ if (prevLsp != null) {
+ configureGraph(graph, prevLsp.getComputedPath(), prevLsp.getIntendedPath().getConstraints(), false);
}
- /* Verify that we have a valid Computed Path and that the LSP is in SYNC */
- if (cfgLsp.getComputedPath().getComputationStatus() != ComputationStatus.Completed
- || cfgLsp.getPathStatus() != PathStatus.Sync) {
- return;
+
+ /* Then add Bandwidth and Triggers for the current path */
+ configureGraph(graph, cfgLsp.getComputedPath(), cfgLsp.getIntendedPath().getConstraints(), true);
+
+ /* And memorize current LSP for latter update */
+ prevLsp = cfgLsp;
+ }
+
+ /**
+ * Reset Triggered Flag.
+ */
+ public void unSetTriggerFlag() {
+ triggerFlag = false;
+ }
+
+ @Override
+ public boolean verifyVertex(final ConnectedVertex next, final Vertex current) {
+ /* Check if there is an on-going trigger */
+ if (triggerFlag) {
+ return false;
}
- /* Verify that a Bandwidth has been requested and reserved */
- if (cfgLsp.getIntendedPath().getConstraints().getBandwidth() == null) {
- return;
+
+ /* Check if Vertex has been removed */
+ Vertex vertex = next.getVertex();
+ if (vertex == null) {
+ triggerFlag = true;
+ return true;
}
- /* Loop the path description to delete reserved bandwidth for this LSP */
- final Long bw = cfgLsp.getIntendedPath().getConstraints().getBandwidth().getValue().longValue();
- int cos = cfgLsp.getIntendedPath().getConstraints().getClassType() != null
- ? cfgLsp.getIntendedPath().getConstraints().getClassType().intValue()
- : 0;
+ /* Check if Vertex changed its Segment Routing Global Block */
final AddressFamily af = cfgLsp.getIntendedPath().getConstraints().getAddressFamily();
- for (PathDescription path : cfgLsp.getComputedPath().getPathDescription()) {
- ConnectedEdge edge = null;
- switch (af) {
- case Ipv4:
- case SrIpv4:
- edge = graph.getConnectedEdge(new IpAddress(path.getIpv4()));
- break;
- case Ipv6:
- case SrIpv6:
- edge = graph.getConnectedEdge(new IpAddress(path.getIpv6()));
- break;
- default:
- break;
- }
- if (edge != null) {
- edge.delBandwidth(bw, cos);
- }
+ if ((af == AddressFamily.SrIpv4 || af == AddressFamily.SrIpv6) && !current.getSrgb().equals(vertex.getSrgb())) {
+ LOG.debug("Vertex {} modified its SRGB {} / {}", vertex.getName(), current.getSrgb(), vertex.getSrgb());
+ triggerFlag = true;
+ return true;
}
+
+ /* All is fine */
+ triggerFlag = false;
+ return false;
}
- public void updateBandwidth(ConnectedGraph graph) {
- /* Check that Connected Graph is valid */
- if (graph == null) {
- return;
+ @Override
+ public boolean verifyEdge(final ConnectedEdge next, final Edge current) {
+ /* Check if there is an on-going trigger */
+ if (triggerFlag) {
+ return false;
+ }
+
+ /* Check if Edge or Attributes has been removed */
+ Edge edge = next.getEdge();
+ if (edge == null || edge.getEdgeAttributes() == null) {
+ triggerFlag = true;
+ return true;
+ }
+
+ /* Check that Configured LSP has valid constraints */
+ final Constraints constraints = cfgLsp.getIntendedPath().getConstraints();
+ if (constraints == null) {
+ return false;
+ }
+
+ /* Check if Metric is always met */
+ Long metric = 0L;
+ Long delta = 0L;
+ if (constraints.getDelay() != null) {
+ if (edge.getEdgeAttributes().getDelay() != null) {
+ metric = constraints.getDelay().getValue().longValue();
+ delta = edge.getEdgeAttributes().getDelay().getValue().longValue()
+ - current.getEdgeAttributes().getDelay().getValue().longValue();
+ } else {
+ triggerFlag = true;
+ return true;
+ }
}
- /* First remove Bandwidth for the old path if any */
- if (prevLsp != null && prevLsp.getIntendedPath().getConstraints().getBandwidth() != null) {
- final Long bw = prevLsp.getIntendedPath().getConstraints().getBandwidth().getValue().longValue();
- int cos = prevLsp.getIntendedPath().getConstraints().getClassType() != null
- ? prevLsp.getIntendedPath().getConstraints().getClassType().intValue()
- : 0;
- final AddressFamily af = prevLsp.getIntendedPath().getConstraints().getAddressFamily();
- for (PathDescription path : prevLsp.getComputedPath().getPathDescription()) {
- ConnectedEdge edge = null;
- switch (af) {
- case Ipv4:
- case SrIpv4:
- edge = graph.getConnectedEdge(new IpAddress(path.getIpv4()));
- break;
- case Ipv6:
- case SrIpv6:
- edge = graph.getConnectedEdge(new IpAddress(path.getIpv6()));
- break;
- default:
- break;
- }
- if (edge != null) {
- edge.delBandwidth(bw, cos);
+ if (constraints.getTeMetric() != null) {
+ if (edge.getEdgeAttributes().getTeMetric() != null) {
+ metric = constraints.getTeMetric().longValue();
+ delta = edge.getEdgeAttributes().getTeMetric().longValue()
+ - current.getEdgeAttributes().getTeMetric().longValue();
+ } else {
+ triggerFlag = true;
+ return true;
+ }
+ } else if (constraints.getMetric() != null) {
+ if (edge.getEdgeAttributes().getMetric() != null) {
+ metric = constraints.getMetric().longValue();
+ delta = edge.getEdgeAttributes().getMetric().longValue()
+ - current.getEdgeAttributes().getMetric().longValue();
+ } else {
+ triggerFlag = true;
+ return true;
+ }
+ }
+ if (metric != 0L && cfgLsp.getComputedPath().getComputedMetric() != null
+ && cfgLsp.getComputedPath().getComputedMetric().longValue() + delta > metric) {
+ LOG.debug("Following an update on Edge {} Metric is no longer guaranteed: {} / {}",
+ edge.getName(),
+ cfgLsp.getComputedPath().getComputedMetric().longValue() + delta,
+ metric);
+ triggerFlag = true;
+ return true;
+ }
+
+ /* Check if Bandwidth is always met */
+ if (constraints.getBandwidth() != null) {
+ if (edge.getEdgeAttributes().getMaxLinkBandwidth() == null
+ || edge.getEdgeAttributes().getMaxResvLinkBandwidth() == null
+ || edge.getEdgeAttributes().getUnreservedBandwidth() == null) {
+ triggerFlag = true;
+ return true;
+ }
+ Long bandwidth = constraints.getBandwidth().getValue().longValue();
+ Long unrsv = 0L;
+ int cos = 0;
+ for (UnreservedBandwidth unResBw : edge.getEdgeAttributes().getUnreservedBandwidth()) {
+ if (unResBw.getClassType().intValue() == cos) {
+ unrsv = unResBw.getBandwidth().getValue().longValue();
+ break;
}
}
+ Long maxBW = edge.getEdgeAttributes().getMaxLinkBandwidth().getValue().longValue();
+ if (bandwidth > List.of(
+ unrsv,
+ /* maxBW might be on the list but will always be greater than the next items */
+ maxBW - next.getCosResvBandwidth(cos),
+ maxBW - next.getGlobalResvBandwidth(),
+ edge.getEdgeAttributes().getMaxResvLinkBandwidth().getValue().longValue())
+ .stream().mapToLong(v -> v)
+ .min().getAsLong()
+ ) {
+ LOG.debug("Following an update on Edge {}, Reserved bandwidth is no longer guaranteed", edge.getName());
+ triggerFlag = true;
+ return true;
+ }
}
- /* Then add Bandwidth for the current path */
- addBandwidth(graph);
- /* And memorize current LSP for latter update */
- prevLsp = cfgLsp;
+
+ /* Check if Edge changed its Adjacency SID */
+ final AddressFamily af = cfgLsp.getIntendedPath().getConstraints().getAddressFamily();
+ if ((af == AddressFamily.SrIpv4 || af == AddressFamily.SrIpv6)
+ && !current.getEdgeAttributes().getAdjSid().equals(edge.getEdgeAttributes().getAdjSid())) {
+ LOG.debug("Edge {} has modified its Adjacency SID", edge.getName());
+ triggerFlag = true;
+ return true;
+ }
+
+ return false;
}
/**
final Ipv4Builder ipBuilder = new Ipv4Builder()
.setDestinationIpv4Address(new Ipv4AddressNoZone(iPath.getDestination().getIpv4Address()))
.setSourceIpv4Address(new Ipv4AddressNoZone(iPath.getSource().getIpv4Address()));
- epb.setAddressFamily((new Ipv4CaseBuilder().setIpv4(ipBuilder.build()).build()));
+ epb.setAddressFamily(new Ipv4CaseBuilder().setIpv4(ipBuilder.build()).build());
} else if (cfgLsp.getIntendedPath().getSource().getIpv6Address() != null) {
final Ipv6Builder ipBuilder = new Ipv6Builder()
.setDestinationIpv6Address(new Ipv6AddressNoZone(iPath.getDestination().getIpv6Address()))
.setSourceIpv6Address(new Ipv6AddressNoZone(iPath.getSource().getIpv6Address()));
- epb.setAddressFamily((new Ipv6CaseBuilder().setIpv6(ipBuilder.build()).build()));
+ epb.setAddressFamily(new Ipv6CaseBuilder().setIpv6(ipBuilder.build()).build());
} else {
// In case of ...
return null;
.setAdministrative(true)
.setDelegate(true);
- /*
- * Build Arguments.
- * Note that TE Metric and Delay are not set because, at least, Juniper Routers don't support them.
- */
+ /* Build Arguments. */
final ArgumentsBuilder args = new ArgumentsBuilder()
.setEndpointsObj(epb.build())
.setEro(MessagesUtil.getEro(cfgLsp.getComputedPath().getPathDescription()))
.setPathSetupType(pstBuilder.build())
.build());
- /* with Bandwidth and Standard Metric */
+ /* with Bandwidth and Metric if defined */
if (iPath.getConstraints().getBandwidth() != null) {
final int ftoi = Float.floatToIntBits(iPath.getConstraints().getBandwidth().getValue().floatValue());
final byte[] itob = { (byte) (0xFF & ftoi >> 24), (byte) (0xFF & ftoi >> 16), (byte) (0xFF & ftoi >> 8),
(byte) (0xFF & ftoi) };
args.setBandwidth(new BandwidthBuilder().setBandwidth(new Bandwidth(itob)).build());
}
- if (iPath.getConstraints().getMetric() != null) {
+ /* Note that Delay are not set because, at least, Juniper Routers don't support them */
+ if (iPath.getConstraints().getTeMetric() != null) {
+ final MetricBuilder metricBuilder = new MetricBuilder()
+ .setComputed(true)
+ .setMetricType(Uint8.TWO)
+ .setValue(new Float32(ByteBuffer.allocate(4)
+ .putFloat(iPath.getConstraints().getTeMetric().floatValue()).array()));
+ args.setMetrics(Collections.singletonList(new MetricsBuilder().setMetric(metricBuilder.build()).build()));
+ } else if (iPath.getConstraints().getMetric() != null) {
final MetricBuilder metricBuilder = new MetricBuilder()
.setComputed(true)
.setMetricType(Uint8.ONE)
/**
* Call add-lsp RPC to enforce the LSP into the PCC. This action will trigger a PcInitiate message to the PCC.
*
- * @param ntps Network Topology PCEP Service
+ * @param addLsp Add Lsp RPC
*
* @return Add LSP Output to convey the RPC result
*/
- public ListenableFuture<RpcResult<AddLspOutput>> addPath(final NetworkTopologyPcepService ntps) {
+ public ListenableFuture<RpcResult<AddLspOutput>> addPath(final AddLsp addLsp) {
/* Check if we could add this path */
- if ((type != PathType.Initiated) || !teNode.isSync()) {
+ if (type != PathType.Initiated || !teNode.isSync()) {
return null;
}
}
sent = true;
- final ListenableFuture<RpcResult<AddLspOutput>> enforce = ntps.addLsp(getAddLspInput());
- LOG.info("Call Add LSP to {} with {}", ntps, enforce);
- Futures.addCallback(enforce, new FutureCallback<RpcResult<AddLspOutput>>() {
+ final var enforce = addLsp.invoke(getAddLspInput());
+ LOG.info("Call Add LSP to {} with {}", addLsp, enforce);
+ Futures.addCallback(enforce, new FutureCallback<>() {
@Override
public void onSuccess(final RpcResult<AddLspOutput> result) {
if (result.isSuccessful()) {
*
* @return new Update LSP Input
*/
- private UpdateLspInput getUpdateLspInput() {
+ private @NonNull UpdateLspInput getUpdateLspInput() {
/* Create Path Setup Type */
final IntendedPath iPath = cfgLsp.getIntendedPath();
final PathSetupTypeBuilder pstBuilder = new PathSetupTypeBuilder();
.setDelegate(true);
/* Build Arguments */
- final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730
.update.lsp.args.ArgumentsBuilder args;
- args = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120
+ args = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730
.update.lsp.args.ArgumentsBuilder()
.addAugmentation(new Arguments3Builder()
.setLsp(lspBuilder.build())
.build())
.setEro(MessagesUtil.getEro(cfgLsp.getComputedPath().getPathDescription()));
- /* with Bandwidth if defined, but not other Metrics as some routers don't support them */
+ /* with Bandwidth and Metric if defined */
if (iPath.getConstraints().getBandwidth() != null) {
final int ftoi = Float.floatToIntBits(iPath.getConstraints().getBandwidth().getValue().floatValue());
final byte[] itob = { (byte) (0xFF & ftoi >> 24), (byte) (0xFF & ftoi >> 16), (byte) (0xFF & ftoi >> 8),
(byte) (0xFF & ftoi) };
args.setBandwidth(new BandwidthBuilder().setBandwidth(new Bandwidth(itob)).build());
}
+ /* Note that Delay are not set because, at least, Juniper Routers don't support them */
+ if (iPath.getConstraints().getTeMetric() != null) {
+ final MetricBuilder metricBuilder = new MetricBuilder()
+ .setComputed(true)
+ .setMetricType(Uint8.TWO)
+ .setValue(new Float32(ByteBuffer.allocate(4)
+ .putFloat(iPath.getConstraints().getTeMetric().floatValue()).array()));
+ args.setMetrics(Collections.singletonList(new MetricsBuilder().setMetric(metricBuilder.build()).build()));
+ } else if (iPath.getConstraints().getMetric() != null) {
+ final MetricBuilder metricBuilder = new MetricBuilder()
+ .setComputed(true)
+ .setMetricType(Uint8.ONE)
+ .setValue(new Float32(ByteBuffer.allocate(4)
+ .putFloat(iPath.getConstraints().getMetric().floatValue()).array()));
+ args.setMetrics(Collections.singletonList(new MetricsBuilder().setMetric(metricBuilder.build()).build()));
+ }
/*
* NOTE: Seems that ClassType is not supported by some routers. Skip it for the moment.
/**
* Call update-lsp RPC to enforce the LSP into the PCC. This action will trigger a PcUpdate message to the PCC.
*
- * @param ntps Network Topology PCEP Service
+ * @param updateLsp Update LSP RPC
*
* @return Update LSP Output to convey the RPC result
*/
- public ListenableFuture<RpcResult<UpdateLspOutput>> updatePath(final NetworkTopologyPcepService ntps) {
+ public ListenableFuture<RpcResult<UpdateLspOutput>> updatePath(final UpdateLsp updateLsp) {
/* Check if we could update this path */
- if ((type != PathType.Initiated && type != PathType.Delegated) || !teNode.isSync()) {
+ if (type != PathType.Initiated && type != PathType.Delegated || !teNode.isSync()) {
return null;
}
sent = true;
final NodeId id = teNode.getId();
- final ListenableFuture<RpcResult<UpdateLspOutput>> enforce = ntps.updateLsp(getUpdateLspInput());
- LOG.info("Call Update LSP to {} with {}", ntps, enforce);
- Futures.addCallback(enforce, new FutureCallback<RpcResult<UpdateLspOutput>>() {
+ final var enforce = updateLsp.invoke(getUpdateLspInput());
+ LOG.info("Call Update LSP to {} with {}", updateLsp, enforce);
+ Futures.addCallback(enforce, new FutureCallback<>() {
@Override
public void onSuccess(final RpcResult<UpdateLspOutput> result) {
if (result.isSuccessful()) {
* Call remove-lsp RPC to remove the LSP from the PCC. This action will trigger a PcInitiate message to the PCC
* with 'R' bit set.
*
- * @param ntps Network Topology PCEP Service
+ * @param removeLsp Remove Lsp RPC
*
* @return Remove LSP Output to convey the RPC result
*/
- public ListenableFuture<RpcResult<RemoveLspOutput>> removePath(final NetworkTopologyPcepService ntps) {
+ public ListenableFuture<RpcResult<RemoveLspOutput>> removePath(final RemoveLsp removeLsp) {
/* Check if we could remove this path */
- if ((type != PathType.Initiated) || !teNode.isSync() || cfgLsp.getPathStatus() != PathStatus.Sync) {
+ if (type != PathType.Initiated || !teNode.isSync() || cfgLsp.getPathStatus() != PathStatus.Sync) {
return null;
}
.setName(cfgLsp.getName())
.setNetworkTopologyRef(new NetworkTopologyRef(pcepTopology))
.build();
- final ListenableFuture<RpcResult<RemoveLspOutput>> enforce = ntps.removeLsp(rli);
- LOG.info("Call Remove LSP to {} with {}", ntps, enforce);
+ final ListenableFuture<RpcResult<RemoveLspOutput>> enforce = removeLsp.invoke(rli);
+ LOG.info("Call Remove LSP to {} with {}", removeLsp, enforce);
Futures.addCallback(enforce, new FutureCallback<RpcResult<RemoveLspOutput>>() {
@Override
public void onSuccess(final RpcResult<RemoveLspOutput> result) {
CodeHelpers.appendValue(helper, "Sent", sent);
return helper.toString();
}
+
}