Add Bandwidth Reservation in PCE server
[bgpcep.git] / pcep / server / server-provider / src / main / java / org / opendaylight / bgpcep / pcep / server / provider / PcepTopologyListener.java
1 /*
2  * Copyright (c) 2021 Orange. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.bgpcep.pcep.server.provider;
9
10 import static java.util.Objects.requireNonNull;
11
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;
75
76 /**
77  * This Class listen to the PCEP Topology in order to trigger Path Manager methods to control Managed TE Path.
78  *
79  * @author Olivier Dugeon
80  */
81
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;
86
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());
97     }
98
99     /**
100      * Close this Listener.
101      */
102     @Override
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;
108         }
109     }
110
111     /**
112      * Handle reported LSP modifications.
113      *
114      * @param nodeId    Node Identifier to which the modified children belongs to.
115      * @param lspMod    List of Reported LSP modifications.
116      */
117     private void handleLspChange(NodeId nodeId, List<? extends DataObjectModification<? extends DataObject>> lspMod) {
118         for (DataObjectModification<? extends DataObject> lsp : lspMod) {
119             ReportedLsp rptLsp;
120
121             switch (lsp.getModificationType()) {
122                 case DELETE:
123                     rptLsp = (ReportedLsp) lsp.getDataBefore();
124                     LOG.debug("Un-Register Managed TE Path: {}", rptLsp.getName());
125                     pathManager.unregisterTePath(nodeId, new ConfiguredLspKey(rptLsp.getName()));
126                     break;
127                 case SUBTREE_MODIFIED:
128                 case WRITE:
129                     rptLsp = (ReportedLsp) lsp.getDataAfter();
130                     LOG.debug("Register Managed TE Path {}", rptLsp.getName());
131                     pathManager.registerTePath(nodeId,  getConfiguredLsp(rptLsp), getPathType(rptLsp));
132                     break;
133                 default:
134                     break;
135             }
136
137         }
138     }
139
140     /**
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.
144      *
145      * @param nodeId    Node Identifier to which the modified children belongs to.
146      * @param pccMod    List of Path Computation Client modifications.
147      */
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()) {
152                 case DELETE:
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 */
156                     return;
157                 case SUBTREE_MODIFIED:
158                 case WRITE:
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);
167                             }
168                             return;
169                         }
170                     } else {
171                         LOG.debug("Register new Managed TE Node {}", nodeId);
172                         pathManager.registerManagedTeNode(nodeId);
173                     }
174                     break;
175                 default:
176                     break;
177             }
178
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);
185             }
186         }
187     }
188
189     /**
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.
192      *
193      * @param nodeId    Node Identifier to which the modified children belongs to.
194      * @param node1Mod  List of Node1 modifications.
195      */
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);
204             }
205         }
206     }
207
208     @Override
209     public void onDataTreeChanged(final Collection<DataTreeModification<Node>> changes) {
210         for (DataTreeModification<Node> change : changes) {
211             DataObjectModification<Node> root = change.getRootNode();
212
213             final NodeId nodeId =
214                 root.getModificationType() == DataObjectModification.ModificationType.DELETE
215                     ? root.getDataBefore().getNodeId()
216                     : root.getDataAfter().getNodeId();
217
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);
225             }
226         }
227     }
228
229     /**
230      * Translate ERO Segment Routing SubOject i.e. NaiType into Path Description.
231      *
232      * @param srObj Segment Routing SubObject.
233      * @param af    Address Family, SR-IPv4 or SR-IPv6.
234      *
235      * @return      Path Description of the corresponding ERO SubObject.
236      */
237     private static PathDescription getSrPath(SrSubobject srObj, final AddressFamily af) {
238         switch (af) {
239             case SrIpv4:
240                 switch (srObj.getNaiType()) {
241                     case Ipv4Adjacency:
242                         return new PathDescriptionBuilder()
243                             .setSid(srObj.getSid())
244                             .setIpv4(((IpAdjacency)(srObj).getNai()).getLocalIpAddress().getIpv4AddressNoZone())
245                             .setRemoteIpv4(((IpAdjacency)(srObj).getNai()).getRemoteIpAddress().getIpv4AddressNoZone())
246                             .build();
247                     case Ipv4NodeId:
248                         return new PathDescriptionBuilder()
249                             .setSid(srObj.getSid())
250                             .setRemoteIpv4(((IpNodeId)(srObj).getNai()).getIpAddress().getIpv4AddressNoZone())
251                             .build();
252                     default:
253                         return null;
254                 }
255             case SrIpv6:
256                 switch (srObj.getNaiType()) {
257                     case Ipv6Adjacency:
258                         return new PathDescriptionBuilder()
259                             .setSid(srObj.getSid())
260                             .setIpv6(((IpAdjacency)(srObj).getNai()).getLocalIpAddress().getIpv6AddressNoZone())
261                             .setRemoteIpv6(((IpAdjacency)(srObj).getNai()).getRemoteIpAddress().getIpv6AddressNoZone())
262                             .build();
263                     case Ipv6NodeId:
264                         return new PathDescriptionBuilder()
265                             .setSid(srObj.getSid())
266                             .setRemoteIpv6(((IpNodeId)(srObj).getNai()).getIpAddress().getIpv6AddressNoZone())
267                             .build();
268                     default:
269                         return null;
270                 }
271             default:
272                 return null;
273         }
274     }
275
276     /**
277      * Translate ERO RSVP-TE SubObject i.e. IpPrefixCase into Path Description.
278      *
279      * @param srObj Segment Routing SubObject.
280      * @param af    Address Family, SR-IPv4 or SR-IPv6.
281      *
282      * @return      Path Description of the corresponding ERO SubObject.
283      */
284     private static PathDescription getIpPath(IpPrefixCase ipc, final AddressFamily af) {
285         switch (af) {
286             case Ipv4:
287                 return new PathDescriptionBuilder().setRemoteIpv4(
288                         new Ipv4Address(ipc.getIpPrefix().getIpPrefix().getIpv4Prefix().getValue().split("/")[0]))
289                         .build();
290             case Ipv6:
291                 return new PathDescriptionBuilder().setRemoteIpv6(
292                         new Ipv6Address(ipc.getIpPrefix().getIpPrefix().getIpv6Prefix().getValue().split("/")[0]))
293                         .build();
294             default:
295                 return null;
296         }
297     }
298
299     /**
300      * Translate RRO RSVP-TE SubObject i.e. IpPrefixCase into Path Description.
301      *
302      * @param srObj Segment Routing SubObject.
303      * @param af    Address Family, SR-IPv4 or SR-IPv6.
304      *
305      * @return      Path Description of the corresponding RRO SubObject.
306      */
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) {
309         switch (af) {
310             case Ipv4:
311                 return new PathDescriptionBuilder().setRemoteIpv4(
312                         new Ipv4Address(ipc.getIpPrefix().getIpPrefix().getIpv4Prefix().getValue().split("/")[0]))
313                         .build();
314             case Ipv6:
315                 return new PathDescriptionBuilder().setRemoteIpv6(
316                         new Ipv6Address(ipc.getIpPrefix().getIpPrefix().getIpv6Prefix().getValue().split("/")[0]))
317                         .build();
318             default:
319                 return null;
320         }
321     }
322
323     /**
324      * Translate Explicit Route Object (ERO) of the LSP into Path Description.
325      *
326      * @param ero   Explicit Route Object.
327      * @param af    Address Family, IPv4 or IPv6.
328      *
329      * @return      Path Description of the corresponding TE Path.
330      */
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));
339             }
340         }
341         return pathDesc.isEmpty() ? null : pathDesc;
342     }
343
344     /**
345      * Translate Record Route Object (RRO) of the LSP into a Path Description.
346      *
347      * @param rro   Record Route Object of the reported LSP.
348      * @param af    Address Family, IPv4, IPv6, SR-IPv4 or SR-IPv6
349      *
350      * @return      Path Description of the corresponding TE Path.
351      */
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));
363             }
364         }
365         return pathDesc.isEmpty() ? null : pathDesc;
366     }
367
368     /**
369      * Build a new TE Path from a reported LSP.
370      *
371      * @param rl    Reported LSP.
372      *
373      * @return      new TE Path.
374      */
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());
378         Float convert;
379         ConstraintsBuilder cb = new ConstraintsBuilder();
380
381         /* Set Constraints */
382         if (path.getClassType() != null) {
383             cb.setClassType(path.getClassType().getClassType().getValue());
384         }
385         if (path.getBandwidth() != null) {
386             convert = ByteBuffer.wrap(path.getBandwidth().getBandwidth().getValue()).getFloat();
387             cb.setBandwidth(new DecimalBandwidth(BigDecimal.valueOf(convert.longValue())));
388         }
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())));
393         }
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;
402                         break;
403                     case MessagesUtil.TE_METRIC:
404                         cb.setTeMetric(Uint32.valueOf(convert.longValue()));
405                         rtype = RoutingType.TeMetric;
406                         break;
407                     case MessagesUtil.PATH_DELAY:
408                         cb.setDelay(new Delay(Uint32.valueOf(convert.longValue())));
409                         rtype = RoutingType.Delay;
410                         break;
411                     default:
412                         break;
413                 }
414             }
415         }
416
417         /* Get Source and Destination addresses and family */
418         if (path.augmentations() == null) {
419             return null;
420         }
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);
438         } else {
439             return null;
440         }
441
442         /* Build Intended Path */
443         final IntendedPathBuilder ipb = new IntendedPathBuilder()
444                 .setSource(source)
445                 .setDestination(destination)
446                 .setRoutingMethod(rtype)
447                 .setConstraints(cb.build());
448
449         /* Build Actual Path */
450         ComputedPathBuilder cpb = new ComputedPathBuilder();
451
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());
458         }
459         if (pathDesc == null
460                 && path.getRro() != null
461                 && path.getRro().getSubobject() != null
462                 && path.getRro().getSubobject().size() > 0) {
463             pathDesc = getPathDescription(path.getRro(), cb.getAddressFamily());
464         }
465         if (pathDesc != null) {
466             cpb.setPathDescription(pathDesc).setComputationStatus(ComputationStatus.Completed);
467         } else {
468             cpb.setComputationStatus(ComputationStatus.Failed);
469         }
470
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())
477                 .build();
478     }
479
480     /**
481      * get Path Type from a reported LSP.
482      *
483      * @param rl    Reported LSP.
484      *
485      * @return      Path Type.
486      */
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()) {
491             return PathType.Pcc;
492         }
493         final Lsp1 lspCreateFlag = p1.getLsp().augmentation(Lsp1.class);
494         if (lspCreateFlag == null || !lspCreateFlag.getCreate()) {
495             return PathType.Delegated;
496         }
497         return PathType.Initiated;
498     }
499
500 }
501