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 java.util.Objects.requireNonNull;
12 import com.google.common.collect.Iterables;
13 import java.nio.ByteBuffer;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.List;
17 import java.util.stream.Collectors;
18 import org.opendaylight.mdsal.binding.api.DataBroker;
19 import org.opendaylight.mdsal.binding.api.DataObjectModification;
20 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
21 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
22 import org.opendaylight.mdsal.binding.api.DataTreeModification;
23 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.DecimalBandwidth;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.Delay;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev220324.AddressFamily;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev220324.ComputationStatus;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev220324.path.descriptions.PathDescription;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev220324.path.descriptions.PathDescriptionBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.initiated.rev200720.Lsp1;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.OperationalStatus;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.Path1;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.identifiers.tlv.lsp.identifiers.address.family.Ipv4Case;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.identifiers.tlv.lsp.identifiers.address.family.Ipv6Case;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.identifiers.tlv.lsp.identifiers.address.family.ipv4._case.Ipv4;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.identifiers.tlv.lsp.identifiers.address.family.ipv6._case.Ipv6;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.object.Lsp;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev200720.SrSubobject;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev200720.sr.subobject.nai.IpAdjacency;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev200720.sr.subobject.nai.IpNodeId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.PathStatus;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.PathType;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.ConfiguredLsp;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.ConfiguredLspBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.ConfiguredLspKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.configured.lsp.ComputedPathBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.configured.lsp.IntendedPathBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev220321.pcc.configured.lsp.configured.lsp.intended.path.ConstraintsBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.Ero;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.ero.Subobject;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.Metrics;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.reported.route.object.Rro;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.SubobjectType;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.IpPrefixCase;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.Node1;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.PccSyncState;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.pcep.client.attributes.PathComputationClient;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.pcep.client.attributes.path.computation.client.ReportedLsp;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.pcep.client.attributes.path.computation.client.reported.lsp.Path;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
67 import org.opendaylight.yangtools.concepts.ListenerRegistration;
68 import org.opendaylight.yangtools.yang.binding.DataObject;
69 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
70 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
71 import org.opendaylight.yangtools.yang.common.Decimal64;
72 import org.opendaylight.yangtools.yang.common.Uint32;
73 import org.opendaylight.yangtools.yang.common.Uint8;
74 import org.slf4j.Logger;
75 import org.slf4j.LoggerFactory;
78 * This Class listen to the PCEP Topology in order to trigger Path Manager methods to control Managed TE Path.
80 * @author Olivier Dugeon
83 public final class PcepTopologyListener implements DataTreeChangeListener<Node>, AutoCloseable {
84 private static final Logger LOG = LoggerFactory.getLogger(PcepTopologyListener.class);
85 private ListenerRegistration<PcepTopologyListener> listenerRegistration;
86 private final PathManagerProvider pathManager;
88 public PcepTopologyListener(final DataBroker dataBroker,
89 final KeyedInstanceIdentifier<Topology, TopologyKey> topology, final PathManagerProvider pathManager) {
90 requireNonNull(dataBroker);
91 requireNonNull(topology);
92 this.pathManager = requireNonNull(pathManager);
93 final InstanceIdentifier<Node> nodeTopology = topology.child(Node.class);
94 listenerRegistration = dataBroker.registerDataTreeChangeListener(
95 DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, nodeTopology), this);
96 LOG.info("Registered PCE Server listener {} for Operational PCEP Topology {}",
97 listenerRegistration, topology.getKey().getTopologyId().getValue());
101 * Close this Listener.
104 public void close() {
105 if (listenerRegistration != null) {
106 LOG.info("Unregistered PCE Server listener {} for Operational PCEP Topology", listenerRegistration);
107 listenerRegistration.close();
108 listenerRegistration = null;
113 * Handle reported LSP modifications.
115 * @param nodeId Node Identifier to which the modified children belongs to.
116 * @param lspMod List of Reported LSP modifications.
118 private void handleLspChange(final NodeId nodeId, final List<DataObjectModification<?>> lspMod) {
119 for (DataObjectModification<?> lsp : lspMod) {
122 switch (lsp.getModificationType()) {
124 rptLsp = (ReportedLsp) lsp.getDataBefore();
125 LOG.debug("Un-Register Managed TE Path: {}", rptLsp.getName());
126 pathManager.unregisterTePath(nodeId, new ConfiguredLspKey(rptLsp.getName()));
128 case SUBTREE_MODIFIED:
130 rptLsp = (ReportedLsp) lsp.getDataAfter();
131 LOG.debug("Register Managed TE Path {}", rptLsp.getName());
132 pathManager.registerTePath(nodeId, getConfiguredLsp(rptLsp), getPathType(rptLsp));
142 * Parse Sub Tree modification. Given list has been filtered to get only Path Computation Client modifications.
143 * This function first create, update or delete Managed TE Node that corresponds to the given NodeId. Then, it
144 * filter the children to retain only the reported LSP modifications.
146 * @param nodeId Node Identifier to which the modified children belongs to.
147 * @param pccMod List of Path Computation Client modifications.
149 private void handlePccChange(final NodeId nodeId, final List<DataObjectModification<?>> pccMod) {
150 for (DataObjectModification<?> node : pccMod) {
151 /* First, process PCC modification */
152 switch (node.getModificationType()) {
154 LOG.debug("Un-Register Managed TE Node: {}", nodeId);
155 pathManager.disableManagedTeNode(nodeId);
156 /* Should stop here to avoid deleting later the associated Managed TE Path */
158 case SUBTREE_MODIFIED:
160 /* First look if the PCC was already created or not yet */
161 if (pathManager.checkManagedTeNode(nodeId)) {
162 /* Check if PCC State is Synchronized */
163 if (node.getModifiedChildren() == null || node.getModifiedChildren().isEmpty()) {
164 PathComputationClient pcc = (PathComputationClient) node.getDataAfter();
165 if (pcc.getStateSync() == PccSyncState.Synchronized) {
166 LOG.debug("Synchronize Managed TE Node {}", nodeId);
167 pathManager.syncManagedTeNode(nodeId);
172 LOG.debug("Register new Managed TE Node {}", nodeId);
173 pathManager.registerManagedTeNode(nodeId);
180 /* Then, look to reported LSP modification */
181 final List<DataObjectModification<? extends DataObject>> lspMod = node.getModifiedChildren()
182 .stream().filter(mod -> mod.getDataType().equals(ReportedLsp.class))
183 .collect(Collectors.toList());
184 if (!lspMod.isEmpty()) {
185 handleLspChange(nodeId, lspMod);
191 * Parse Sub Tree modification. Given children list has been filtered to get only Node1 modifications.
192 * This function filter again this given list to retain only PathComputationClient modifications.
194 * @param nodeId Node Identifier to which the modified children belongs to.
195 * @param node1Mod List of Node1 modifications.
197 private void handleNode1Change(final NodeId nodeId, final List<DataObjectModification<?>> node1Mod) {
198 for (DataObjectModification<?> child : node1Mod) {
199 /* Then, look only to PathComputationClient.class modification */
200 final List<DataObjectModification<?>> pccMod = child.getModifiedChildren()
201 .stream().filter(mod -> mod.getDataType().equals(PathComputationClient.class))
202 .collect(Collectors.toList());
203 if (!pccMod.isEmpty()) {
204 handlePccChange(nodeId, pccMod);
210 public void onDataTreeChanged(final Collection<DataTreeModification<Node>> changes) {
211 for (DataTreeModification<Node> change : changes) {
212 DataObjectModification<Node> root = change.getRootNode();
214 final NodeId nodeId =
215 root.getModificationType() == DataObjectModification.ModificationType.DELETE
216 ? root.getDataBefore().getNodeId()
217 : root.getDataAfter().getNodeId();
219 /* Look only to Node1.class modification */
220 final List<DataObjectModification<?>> node1Mod = root.getModifiedChildren().stream()
221 .filter(mod -> mod.getDataType().equals(Node1.class))
222 .collect(Collectors.toList());
223 if (!node1Mod.isEmpty()) {
224 handleNode1Change(nodeId, node1Mod);
230 * Translate ERO Segment Routing SubOject i.e. NaiType into Path Description.
232 * @param srObj Segment Routing SubObject.
233 * @param af Address Family, SR-IPv4 or SR-IPv6.
235 * @return Path Description of the corresponding ERO SubObject.
237 private static PathDescription getSrPath(final SrSubobject srObj, final AddressFamily af) {
240 switch (srObj.getNaiType()) {
242 return new PathDescriptionBuilder()
243 .setSid(srObj.getSid())
244 .setIpv4(((IpAdjacency)srObj.getNai()).getLocalIpAddress().getIpv4AddressNoZone())
245 .setRemoteIpv4(((IpAdjacency)srObj.getNai()).getRemoteIpAddress().getIpv4AddressNoZone())
248 return new PathDescriptionBuilder()
249 .setSid(srObj.getSid())
250 .setRemoteIpv4(((IpNodeId)srObj.getNai()).getIpAddress().getIpv4AddressNoZone())
256 switch (srObj.getNaiType()) {
258 return new PathDescriptionBuilder()
259 .setSid(srObj.getSid())
260 .setIpv6(((IpAdjacency)srObj.getNai()).getLocalIpAddress().getIpv6AddressNoZone())
261 .setRemoteIpv6(((IpAdjacency)srObj.getNai()).getRemoteIpAddress().getIpv6AddressNoZone())
264 return new PathDescriptionBuilder()
265 .setSid(srObj.getSid())
266 .setRemoteIpv6(((IpNodeId)srObj.getNai()).getIpAddress().getIpv6AddressNoZone())
277 * Translate ERO RSVP-TE SubObject i.e. IpPrefixCase into Path Description.
279 * @param srObj Segment Routing SubObject.
280 * @param af Address Family, SR-IPv4 or SR-IPv6.
282 * @return Path Description of the corresponding ERO SubObject.
284 private static PathDescription getIpPath(final IpPrefixCase ipc, final AddressFamily af) {
287 return new PathDescriptionBuilder().setRemoteIpv4(
288 new Ipv4Address(ipc.getIpPrefix().getIpPrefix().getIpv4Prefix().getValue().split("/")[0]))
291 return new PathDescriptionBuilder().setRemoteIpv6(
292 new Ipv6Address(ipc.getIpPrefix().getIpPrefix().getIpv6Prefix().getValue().split("/")[0]))
300 * Translate RRO RSVP-TE SubObject i.e. IpPrefixCase into Path Description.
302 * @param srObj Segment Routing SubObject.
303 * @param af Address Family, SR-IPv4 or SR-IPv6.
305 * @return Path Description of the corresponding RRO SubObject.
307 private static PathDescription getIpPath(final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang
308 .rsvp.rev150820._record.route.subobjects.subobject.type.IpPrefixCase ipc, final AddressFamily af) {
311 return new PathDescriptionBuilder().setRemoteIpv4(
312 new Ipv4Address(ipc.getIpPrefix().getIpPrefix().getIpv4Prefix().getValue().split("/")[0]))
315 return new PathDescriptionBuilder().setRemoteIpv6(
316 new Ipv6Address(ipc.getIpPrefix().getIpPrefix().getIpv6Prefix().getValue().split("/")[0]))
324 * Translate Explicit Route Object (ERO) of the LSP into Path Description.
326 * @param ero Explicit Route Object.
327 * @param af Address Family, IPv4 or IPv6.
329 * @return Path Description of the corresponding TE Path.
331 private static List<PathDescription> getPathDescription(final Ero ero, final AddressFamily af) {
332 final ArrayList<PathDescription> pathDesc = new ArrayList<>();
333 for (Subobject element : ero.getSubobject()) {
334 final SubobjectType sbt = element.getSubobjectType();
335 if (sbt instanceof SrSubobject) {
336 pathDesc.add(getSrPath((SrSubobject) sbt, af));
337 } else if (sbt instanceof IpPrefixCase) {
338 pathDesc.add(getIpPath((IpPrefixCase) sbt, af));
341 return pathDesc.isEmpty() ? null : pathDesc;
345 * Translate Record Route Object (RRO) of the LSP into a Path Description.
347 * @param rro Record Route Object of the reported LSP.
348 * @param af Address Family, IPv4, IPv6, SR-IPv4 or SR-IPv6
350 * @return Path Description of the corresponding TE Path.
352 private static List<PathDescription> getPathDescription(final Rro rro, final AddressFamily af) {
353 final ArrayList<PathDescription> pathDesc = new ArrayList<>();
354 for (var element : rro.nonnullSubobject()) {
355 final var sbt = element.getSubobjectType();
356 if (sbt instanceof SrSubobject) {
357 pathDesc.add(getSrPath((SrSubobject) sbt, af));
358 } else if (sbt instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820
359 ._record.route.subobjects.subobject.type.IpPrefixCase) {
360 pathDesc.add(getIpPath((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820
361 ._record.route.subobjects.subobject.type.IpPrefixCase)sbt, af));
364 return pathDesc.isEmpty() ? null : pathDesc;
368 * Build a new TE Path from a reported LSP.
370 * @param rl Reported LSP.
372 * @return new TE Path.
374 private static ConfiguredLsp getConfiguredLsp(final ReportedLsp rl) {
375 /* New reported LSP is always the last Path in the List i.e. old Paths are place before */
376 Path path = Iterables.getLast(rl.getPath().values());
378 ConstraintsBuilder cb = new ConstraintsBuilder();
380 /* Set Constraints */
381 if (path.getClassType() != null) {
382 cb.setClassType(path.getClassType().getClassType().getValue());
384 if (path.getBandwidth() != null) {
385 convert = ByteBuffer.wrap(path.getBandwidth().getBandwidth().getValue()).getFloat();
386 cb.setBandwidth(new DecimalBandwidth(Decimal64.valueOf(2, convert.longValue())));
388 if ((cb.getBandwidth() == null || cb.getBandwidth().getValue().equals(Decimal64.valueOf(2, 0)))
389 && path.getReoptimizationBandwidth() != null) {
390 convert = ByteBuffer.wrap(path.getReoptimizationBandwidth().getBandwidth().getValue()).getFloat();
391 cb.setBandwidth(new DecimalBandwidth(Decimal64.valueOf(2, convert.longValue())));
393 if (path.getMetrics() != null) {
394 for (Metrics metric: path.getMetrics()) {
395 convert = ByteBuffer.wrap(metric.getMetric().getValue().getValue()).getFloat();
396 switch (metric.getMetric().getMetricType().intValue()) {
397 case MessagesUtil.IGP_METRIC:
398 cb.setMetric(Uint32.valueOf(convert.longValue()));
400 case MessagesUtil.TE_METRIC:
401 cb.setTeMetric(Uint32.valueOf(convert.longValue()));
403 case MessagesUtil.PATH_DELAY:
404 cb.setDelay(new Delay(Uint32.valueOf(convert.longValue())));
412 /* Get Source and Destination addresses and family */
413 if (path.augmentations() == null) {
416 final Path1 p1 = path.augmentation(Path1.class);
417 final Uint8 pst = p1.getPathSetupType() != null ? p1.getPathSetupType().getPst() : Uint8.ZERO;
418 final Lsp lsp = p1.getLsp();
419 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp
420 .identifiers.tlv.lsp.identifiers.AddressFamily af = lsp.getTlvs().getLspIdentifiers().getAddressFamily();
421 IpAddress source = null;
422 IpAddress destination = null;
423 if (af instanceof Ipv4Case) {
424 final Ipv4 ipv4 = ((Ipv4Case) af).getIpv4();
425 source = new IpAddress(ipv4.getIpv4TunnelSenderAddress());
426 destination = new IpAddress(ipv4.getIpv4TunnelEndpointAddress());
427 cb.setAddressFamily(pst == Uint8.ZERO ? AddressFamily.Ipv4 : AddressFamily.SrIpv4);
428 } else if (af instanceof Ipv6Case) {
429 final Ipv6 ipv6 = ((Ipv6Case) af).getIpv6();
430 source = new IpAddress(ipv6.getIpv6TunnelSenderAddress());
431 destination = new IpAddress(ipv6.getIpv6TunnelSenderAddress());
432 cb.setAddressFamily(pst == Uint8.ZERO ? AddressFamily.Ipv6 : AddressFamily.SrIpv6);
437 /* Build Intended Path */
438 final IntendedPathBuilder ipb = new IntendedPathBuilder()
440 .setDestination(destination)
441 .setConstraints(cb.build());
443 /* Get a Valid Path Description for this TePath if any */
444 List<PathDescription> pathDesc = null;
445 if (path.getEro() != null
446 && path.getEro().getSubobject() != null
447 && path.getEro().getSubobject().size() > 0) {
448 pathDesc = getPathDescription(path.getEro(), cb.getAddressFamily());
451 && path.getRro() != null
452 && path.getRro().getSubobject() != null
453 && path.getRro().getSubobject().size() > 0) {
454 pathDesc = getPathDescription(path.getRro(), cb.getAddressFamily());
457 ConfiguredLspBuilder clb =
458 new ConfiguredLspBuilder()
459 .setName(rl.getName())
460 .setPathStatus(PathStatus.Reported)
461 .setIntendedPath(ipb.build());
463 /* Finally Build Actual Path and TE Path */
464 if (pathDesc == null) {
465 return clb.setComputedPath(
466 new ComputedPathBuilder().setComputationStatus(ComputationStatus.Failed).build())
469 return clb.setComputedPath(
470 new ComputedPathBuilder()
471 .setPathDescription(pathDesc)
472 .setComputationStatus(
473 lsp.getOperational() == OperationalStatus.Down
474 ? ComputationStatus.Failed
475 : ComputationStatus.Completed)
481 * get Path Type from a reported LSP.
483 * @param rl Reported LSP.
487 private static PathType getPathType(final ReportedLsp rl) {
488 /* New reported LSP is always the last Path in the List i.e. old Paths are place before */
489 final Path1 p1 = Iterables.getLast(rl.getPath().values()).augmentation(Path1.class);
490 if (!p1.getLsp().getDelegate()) {
493 final Lsp1 lspCreateFlag = p1.getLsp().augmentation(Lsp1.class);
494 if (lspCreateFlag == null || !lspCreateFlag.getCreate()) {
495 return PathType.Delegated;
497 return PathType.Initiated;