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.math.BigDecimal;
14 import java.nio.ByteBuffer;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.List;
18 import java.util.stream.Collectors;
19 import org.opendaylight.mdsal.binding.api.DataBroker;
20 import org.opendaylight.mdsal.binding.api.DataObjectModification;
21 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
22 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
23 import org.opendaylight.mdsal.binding.api.DataTreeModification;
24 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.DecimalBandwidth;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.Delay;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.AddressFamily;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.ComputationStatus;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.path.descriptions.PathDescription;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.path.descriptions.PathDescriptionBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.initiated.rev200720.Lsp1;
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.rev210720.PathStatus;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.PathType;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.RoutingType;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.pcc.configured.lsp.ConfiguredLsp;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.pcc.configured.lsp.ConfiguredLspBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.pcc.configured.lsp.ConfiguredLspKey;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.pcc.configured.lsp.configured.lsp.ComputedPathBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.pcc.configured.lsp.configured.lsp.IntendedPathBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.server.rev210720.pcc.configured.lsp.configured.lsp.intended.path.ConstraintsBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.Ero;
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.rev200120.Node1;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.PccSyncState;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.pcep.client.attributes.PathComputationClient;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.pcep.client.attributes.path.computation.client.ReportedLsp;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.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.Uint32;
72 import org.opendaylight.yangtools.yang.common.Uint8;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
77 * This Class listen to the PCEP Topology in order to trigger Path Manager methods to control Managed TE Path.
79 * @author Olivier Dugeon
82 public final class PcepTopologyListener implements DataTreeChangeListener<Node>, AutoCloseable {
83 private static final Logger LOG = LoggerFactory.getLogger(PcepTopologyListener.class);
84 private ListenerRegistration<PcepTopologyListener> listenerRegistration;
85 private final PathManagerProvider pathManager;
87 public PcepTopologyListener(final DataBroker dataBroker, KeyedInstanceIdentifier<Topology, TopologyKey> topology,
88 final PathManagerProvider pathManager) {
89 requireNonNull(dataBroker);
90 requireNonNull(topology);
91 this.pathManager = requireNonNull(pathManager);
92 final InstanceIdentifier<Node> nodeTopology = topology.child(Node.class);
93 this.listenerRegistration = dataBroker.registerDataTreeChangeListener(
94 DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, nodeTopology), this);
95 LOG.info("Registered PCE Server listener {} for Operational PCEP Topology {}",
96 listenerRegistration, topology.getKey().getTopologyId().getValue());
100 * Close this Listener.
103 public void close() {
104 if (this.listenerRegistration != null) {
105 LOG.info("Unregistered PCE Server listener {} for Operational PCEP Topology", listenerRegistration);
106 this.listenerRegistration.close();
107 this.listenerRegistration = null;
112 * Handle reported LSP modifications.
114 * @param nodeId Node Identifier to which the modified children belongs to.
115 * @param lspMod List of Reported LSP modifications.
117 private void handleLspChange(NodeId nodeId, List<? extends DataObjectModification<? extends DataObject>> lspMod) {
118 for (DataObjectModification<? extends DataObject> lsp : lspMod) {
121 switch (lsp.getModificationType()) {
123 rptLsp = (ReportedLsp) lsp.getDataBefore();
124 LOG.debug("Un-Register Managed TE Path: {}", rptLsp.getName());
125 pathManager.unregisterTePath(nodeId, new ConfiguredLspKey(rptLsp.getName()));
127 case SUBTREE_MODIFIED:
129 rptLsp = (ReportedLsp) lsp.getDataAfter();
130 LOG.debug("Register Managed TE Path {}", rptLsp.getName());
131 pathManager.registerTePath(nodeId, getConfiguredLsp(rptLsp), getPathType(rptLsp));
141 * Parse Sub Tree modification. Given list has been filtered to get only Path Computation Client modifications.
142 * This function first create, update or delete Managed TE Node that corresponds to the given NodeId. Then, it
143 * filter the children to retain only the reported LSP modifications.
145 * @param nodeId Node Identifier to which the modified children belongs to.
146 * @param pccMod List of Path Computation Client modifications.
148 private void handlePccChange(NodeId nodeId, List<? extends DataObjectModification<? extends DataObject>> pccMod) {
149 for (DataObjectModification<? extends DataObject> node : pccMod) {
150 /* First, process PCC modification */
151 switch (node.getModificationType()) {
153 LOG.debug("Un-Register Managed TE Node: {}", nodeId);
154 pathManager.disableManagedTeNode(nodeId);
155 /* Should stop here to avoid deleting later the associated Managed TE Path */
157 case SUBTREE_MODIFIED:
159 /* First look if the PCC was already created or not yet */
160 if (pathManager.checkManagedTeNode(nodeId)) {
161 /* Check if PCC State is Synchronized */
162 if (node.getModifiedChildren() == null || node.getModifiedChildren().isEmpty()) {
163 PathComputationClient pcc = (PathComputationClient) node.getDataAfter();
164 if (pcc.getStateSync() == PccSyncState.Synchronized) {
165 LOG.debug("Synchronize Managed TE Node {}", nodeId);
166 pathManager.syncManagedTeNode(nodeId);
171 LOG.debug("Register new Managed TE Node {}", nodeId);
172 pathManager.registerManagedTeNode(nodeId);
179 /* Then, look to reported LSP modification */
180 final List<DataObjectModification<? extends DataObject>> lspMod = node.getModifiedChildren()
181 .stream().filter(mod -> mod.getDataType().equals(ReportedLsp.class))
182 .collect(Collectors.toList());
183 if (!lspMod.isEmpty()) {
184 handleLspChange(nodeId, lspMod);
190 * Parse Sub Tree modification. Given children list has been filtered to get only Node1 modifications.
191 * This function filter again this given list to retain only PathComputationClient modifications.
193 * @param nodeId Node Identifier to which the modified children belongs to.
194 * @param node1Mod List of Node1 modifications.
196 private void handleNode1Change(NodeId nodeId, List<DataObjectModification<? extends DataObject>> node1Mod) {
197 for (DataObjectModification<? extends DataObject> child : node1Mod) {
198 /* Then, look only to PathComputationClient.class modification */
199 final List<DataObjectModification<? extends DataObject>> pccMod = child.getModifiedChildren()
200 .stream().filter(mod -> mod.getDataType().equals(PathComputationClient.class))
201 .collect(Collectors.toList());
202 if (!pccMod.isEmpty()) {
203 handlePccChange(nodeId, pccMod);
209 public void onDataTreeChanged(final Collection<DataTreeModification<Node>> changes) {
210 for (DataTreeModification<Node> change : changes) {
211 DataObjectModification<Node> root = change.getRootNode();
213 final NodeId nodeId =
214 root.getModificationType() == DataObjectModification.ModificationType.DELETE
215 ? root.getDataBefore().getNodeId()
216 : root.getDataAfter().getNodeId();
218 /* Look only to Node1.class modification */
219 final List<DataObjectModification<? extends DataObject>> node1Mod =
220 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(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(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(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<PathDescription>();
333 for (int i = 0; i < ero.getSubobject().size(); i++) {
334 final SubobjectType sbt = ero.getSubobject().get(i).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<PathDescription>();
354 for (int i = 0; i < rro.getSubobject().size(); i++) {
355 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820
356 ._record.route.subobjects.SubobjectType sbt = rro.getSubobject().get(i).getSubobjectType();
357 if (sbt instanceof SrSubobject) {
358 pathDesc.add(getSrPath((SrSubobject) sbt, af));
359 } else if (sbt instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820
360 ._record.route.subobjects.subobject.type.IpPrefixCase) {
361 pathDesc.add(getIpPath((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820
362 ._record.route.subobjects.subobject.type.IpPrefixCase)sbt, af));
365 return pathDesc.isEmpty() ? null : pathDesc;
369 * Build a new TE Path from a reported LSP.
371 * @param rl Reported LSP.
373 * @return new TE Path.
375 private static ConfiguredLsp getConfiguredLsp(ReportedLsp rl) {
376 /* New reported LSP is always the last Path in the List i.e. old Paths are place before */
377 Path path = Iterables.getLast(rl.getPath().values());
379 ConstraintsBuilder cb = new ConstraintsBuilder();
381 /* Set Constraints */
382 if (path.getClassType() != null) {
383 cb.setClassType(path.getClassType().getClassType().getValue());
385 if (path.getBandwidth() != null) {
386 convert = ByteBuffer.wrap(path.getBandwidth().getBandwidth().getValue()).getFloat();
387 cb.setBandwidth(new DecimalBandwidth(BigDecimal.valueOf(convert.longValue())));
389 if ((cb.getBandwidth() == null || cb.getBandwidth().getValue() == BigDecimal.ZERO)
390 && path.getReoptimizationBandwidth() != null) {
391 convert = ByteBuffer.wrap(path.getReoptimizationBandwidth().getBandwidth().getValue()).getFloat();
392 cb.setBandwidth(new DecimalBandwidth(BigDecimal.valueOf(convert.longValue())));
394 RoutingType rtype = RoutingType.None;
395 if (path.getMetrics() != null) {
396 for (Metrics metric: path.getMetrics()) {
397 convert = ByteBuffer.wrap(metric.getMetric().getValue().getValue()).getFloat();
398 switch (metric.getMetric().getMetricType().intValue()) {
399 case MessagesUtil.IGP_METRIC:
400 cb.setMetric(Uint32.valueOf(convert.longValue()));
401 rtype = RoutingType.Metric;
403 case MessagesUtil.TE_METRIC:
404 cb.setTeMetric(Uint32.valueOf(convert.longValue()));
405 rtype = RoutingType.TeMetric;
407 case MessagesUtil.PATH_DELAY:
408 cb.setDelay(new Delay(Uint32.valueOf(convert.longValue())));
409 rtype = RoutingType.Delay;
417 /* Get Source and Destination addresses and family */
418 if (path.augmentations() == null) {
421 final Path1 p1 = path.augmentation(Path1.class);
422 final Uint8 pst = p1.getPathSetupType() != null ? p1.getPathSetupType().getPst() : Uint8.ZERO;
423 final Lsp lsp = p1.getLsp();
424 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp
425 .identifiers.tlv.lsp.identifiers.AddressFamily af = lsp.getTlvs().getLspIdentifiers().getAddressFamily();
426 IpAddress source = null;
427 IpAddress destination = null;
428 if (af instanceof Ipv4Case) {
429 final Ipv4 ipv4 = ((Ipv4Case) af).getIpv4();
430 source = new IpAddress(ipv4.getIpv4TunnelSenderAddress());
431 destination = new IpAddress(ipv4.getIpv4TunnelEndpointAddress());
432 cb.setAddressFamily(pst == Uint8.ZERO ? AddressFamily.Ipv4 : AddressFamily.SrIpv4);
433 } else if (af instanceof Ipv6Case) {
434 final Ipv6 ipv6 = ((Ipv6Case) af).getIpv6();
435 source = new IpAddress(ipv6.getIpv6TunnelSenderAddress());
436 destination = new IpAddress(ipv6.getIpv6TunnelSenderAddress());
437 cb.setAddressFamily(pst == Uint8.ZERO ? AddressFamily.Ipv6 : AddressFamily.SrIpv6);
442 /* Build Intended Path */
443 final IntendedPathBuilder ipb = new IntendedPathBuilder()
445 .setDestination(destination)
446 .setRoutingMethod(rtype)
447 .setConstraints(cb.build());
449 /* Build Actual Path */
450 ComputedPathBuilder cpb = new ComputedPathBuilder();
452 /* Get a Valid Path Description for this TePath if any */
453 List<PathDescription> pathDesc = null;
454 if (path.getEro() != null
455 && path.getEro().getSubobject() != null
456 && path.getEro().getSubobject().size() > 0) {
457 pathDesc = getPathDescription(path.getEro(), cb.getAddressFamily());
460 && path.getRro() != null
461 && path.getRro().getSubobject() != null
462 && path.getRro().getSubobject().size() > 0) {
463 pathDesc = getPathDescription(path.getRro(), cb.getAddressFamily());
465 if (pathDesc != null) {
466 cpb.setPathDescription(pathDesc).setComputationStatus(ComputationStatus.Completed);
468 cpb.setComputationStatus(ComputationStatus.Failed);
471 /* Finally build TE Path */
472 return new ConfiguredLspBuilder()
473 .setName(rl.getName())
474 .setPathStatus(PathStatus.Reported)
475 .setIntendedPath(ipb.build())
476 .setComputedPath(cpb.build())
481 * get Path Type from a reported LSP.
483 * @param rl Reported LSP.
487 private static PathType getPathType(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;