Remove TopologySessionListenerFactory
[bgpcep.git] / pcep / topology / topology-provider / src / main / java / org / opendaylight / bgpcep / pcep / topology / provider / PCEPTopologySessionListener.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  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.topology.provider;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static com.google.common.base.Preconditions.checkState;
12 import static java.util.Objects.requireNonNull;
13
14 import com.google.common.util.concurrent.AsyncFunction;
15 import com.google.common.util.concurrent.FluentFuture;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import com.google.common.util.concurrent.MoreExecutors;
19 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
20 import java.net.InetAddress;
21 import java.nio.ByteBuffer;
22 import java.nio.charset.StandardCharsets;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Optional;
28 import java.util.concurrent.atomic.AtomicBoolean;
29 import java.util.concurrent.atomic.AtomicLong;
30 import org.checkerframework.checker.lock.qual.GuardedBy;
31 import org.checkerframework.checker.lock.qual.Holding;
32 import org.eclipse.jdt.annotation.NonNull;
33 import org.opendaylight.bgpcep.pcep.server.PathComputation;
34 import org.opendaylight.bgpcep.pcep.server.PceServerProvider;
35 import org.opendaylight.protocol.pcep.PCEPSession;
36 import org.opendaylight.protocol.pcep.spi.PCEPErrors;
37 import org.opendaylight.protocol.pcep.spi.PSTUtil;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev200720.PathComputationClient1Builder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.pcep.sync.optimizations.rev200720.lsp.db.version.tlv.LspDbVersion;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.initiated.rev200720.Lsp1;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.initiated.rev200720.PcinitiateBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.initiated.rev200720.Srp1;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.initiated.rev200720.Srp1Builder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.initiated.rev200720.Stateful1;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.initiated.rev200720.pcinitiate.message.PcinitiateMessageBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.initiated.rev200720.pcinitiate.message.pcinitiate.message.Requests;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.initiated.rev200720.pcinitiate.message.pcinitiate.message.RequestsBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.Arguments1;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.Arguments2;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.Arguments3;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.OperationalStatus;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.Path1;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.Path1Builder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.PcrptMessage;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.PcupdBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.PlspId;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.SrpIdNumber;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.StatefulTlv1Builder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.SymbolicPathName;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.Tlvs1;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.object.Lsp;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.object.LspBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.object.lsp.TlvsBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.pcerr.pcerr.message.error.type.StatefulCase;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.pcerr.pcerr.message.error.type.stateful._case.stateful.Srps;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.pcrpt.message.pcrpt.message.Reports;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.pcupd.message.PcupdMessageBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.pcupd.message.pcupd.message.UpdatesBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.pcupd.message.pcupd.message.updates.PathBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.srp.object.Srp;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.srp.object.SrpBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.stateful.capability.tlv.Stateful;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.symbolic.path.name.tlv.SymbolicPathNameBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.Pcerr;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.PcerrBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.Pcreq;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.Message;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.PcerrMessage;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.RequestId;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.EroBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.open.object.open.Tlvs;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.path.setup.type.tlv.PathSetupType;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcep.error.object.ErrorObjectBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.PcerrMessageBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.ErrorsBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.error.type.RequestCaseBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.error.type.request._case.RequestBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.error.type.request._case.request.RpsBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.PcreqMessage;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.rp.object.RpBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.AddLspArgs;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.EnsureLspOperationalInput;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.LspId;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.Node1;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.OperationResult;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.PccSyncState;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.RemoveLspArgs;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.TriggerSyncArgs;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.UpdateLspArgs;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.ensure.lsp.operational.args.Arguments;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.pcep.client.attributes.PathComputationClient;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.pcep.client.attributes.PathComputationClientBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.pcep.client.attributes.path.computation.client.ReportedLsp;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.pcep.client.attributes.path.computation.client.ReportedLspBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.pcep.client.attributes.path.computation.client.StatefulTlvBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.pcep.client.attributes.path.computation.client.reported.lsp.Path;
107 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
108 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
109 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
110 import org.opendaylight.yangtools.yang.common.Uint32;
111 import org.slf4j.Logger;
112 import org.slf4j.LoggerFactory;
113
114 // Non-final for testing
115 class PCEPTopologySessionListener extends AbstractTopologySessionListener<SrpIdNumber, PlspId> {
116     private static final Logger LOG = LoggerFactory.getLogger(PCEPTopologySessionListener.class);
117     private static final PlspId PLSPID_ZERO = new PlspId(Uint32.ZERO);
118
119     private final AtomicLong requestId = new AtomicLong(1L);
120
121     @GuardedBy("this")
122     private final List<PlspId> staleLsps = new ArrayList<>();
123
124     private final AtomicBoolean statefulCapability = new AtomicBoolean(false);
125     private final AtomicBoolean lspUpdateCapability = new AtomicBoolean(false);
126     private final AtomicBoolean initiationCapability = new AtomicBoolean(false);
127
128     private final PceServerProvider pceServerProvider;
129
130     /**
131      * Creates a new stateful topology session listener for given server session manager.
132      */
133     PCEPTopologySessionListener(final ServerSessionManager serverSessionManager) {
134         super(serverSessionManager);
135         pceServerProvider = serverSessionManager.getPCEPTopologyProviderDependencies().getPceServerProvider();
136     }
137
138     private static LspDbVersion geLspDbVersionTlv(final Lsp lsp) {
139         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.object
140                 .lsp.Tlvs tlvs = lsp.getTlvs();
141         if (tlvs != null && tlvs.augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang
142                 .controller.pcep.sync.optimizations.rev200720.Tlvs1.class) != null) {
143             return tlvs.augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller
144                     .pcep.sync.optimizations.rev200720.Tlvs1.class).getLspDbVersion();
145         }
146         return null;
147     }
148
149     @Override
150     protected void onSessionUp(final PCEPSession session, final PathComputationClientBuilder pccBuilder) {
151         final InetAddress peerAddress = session.getRemoteAddress();
152
153         final Tlvs tlvs = session.getRemoteTlvs();
154         if (tlvs != null && tlvs.augmentation(Tlvs1.class) != null) {
155             final Stateful stateful = tlvs.augmentation(Tlvs1.class).getStateful();
156             if (stateful != null) {
157                 setStatefulCapabilities(stateful);
158                 pccBuilder.setReportedLsp(Collections.emptyMap());
159                 if (isSynchronized()) {
160                     pccBuilder.setStateSync(PccSyncState.Synchronized);
161                 } else if (isTriggeredInitialSynchro()) {
162                     pccBuilder.setStateSync(PccSyncState.TriggeredInitialSync);
163                 } else if (isIncrementalSynchro()) {
164                     pccBuilder.setStateSync(PccSyncState.IncrementalSync);
165                 } else {
166                     pccBuilder.setStateSync(PccSyncState.InitialResync);
167                 }
168                 pccBuilder.setStatefulTlv(new StatefulTlvBuilder().addAugmentation(
169                         new StatefulTlv1Builder(tlvs.augmentation(Tlvs1.class)).build()).build());
170             } else {
171                 LOG.debug("Peer {} does not advertise stateful TLV", peerAddress);
172             }
173         } else {
174             LOG.debug("Peer {} does not advertise stateful TLV", peerAddress);
175         }
176     }
177
178     @Override
179     public synchronized ListenableFuture<OperationResult> triggerSync(final TriggerSyncArgs input) {
180         if (isTriggeredInitialSynchro() && !isSynchronized()) {
181             return triggerSynchronization(input);
182         } else if (isSessionSynchronized() && isTriggeredReSyncEnabled()) {
183             checkArgument(input != null && input.getNode() != null, MISSING_XML_TAG);
184             return input.getName() == null ? triggerResyncronization(input) : triggerLspSyncronization(input);
185         }
186         return OperationResults.UNSENT.future();
187     }
188
189     private ListenableFuture<OperationResult> triggerLspSyncronization(final TriggerSyncArgs input) {
190         LOG.trace("Trigger Lsp Resynchronization {}", input);
191
192         // Make sure the LSP exists
193         final InstanceIdentifier<ReportedLsp> lsp = lspIdentifier(input.getName());
194         final FluentFuture<Optional<ReportedLsp>> f = readOperationalData(lsp);
195         if (f == null) {
196             return OperationResults.createUnsent(PCEPErrors.LSP_INTERNAL_ERROR).future();
197         }
198         return Futures.transformAsync(f, new ResyncLspFunction(input), MoreExecutors.directExecutor());
199     }
200
201     private ListenableFuture<OperationResult> triggerResyncronization(final TriggerSyncArgs input) {
202         LOG.trace("Trigger Resynchronization {}", input);
203         markAllLspAsStale();
204         updatePccState(PccSyncState.PcepTriggeredResync);
205         final PcupdMessageBuilder pcupdMessageBuilder = new PcupdMessageBuilder(MESSAGE_HEADER);
206         final SrpIdNumber srpIdNumber = createUpdateMessageSync(pcupdMessageBuilder);
207         final Message msg = new PcupdBuilder().setPcupdMessage(pcupdMessageBuilder.build()).build();
208         return sendMessage(msg, srpIdNumber, null);
209     }
210
211     private ListenableFuture<OperationResult> triggerSynchronization(final TriggerSyncArgs input) {
212         LOG.trace("Trigger Initial Synchronization {}", input);
213         final PcupdMessageBuilder pcupdMessageBuilder = new PcupdMessageBuilder(MESSAGE_HEADER);
214         final SrpIdNumber srpIdNumber = createUpdateMessageSync(pcupdMessageBuilder);
215         final Message msg = new PcupdBuilder().setPcupdMessage(pcupdMessageBuilder.build()).build();
216         return sendMessage(msg, srpIdNumber, null);
217     }
218
219     private SrpIdNumber createUpdateMessageSync(final PcupdMessageBuilder pcupdMessageBuilder) {
220         final UpdatesBuilder updBuilder = new UpdatesBuilder();
221         // LSP mandatory in Upd
222         final Lsp lsp = new LspBuilder().setPlspId(PLSPID_ZERO).setSync(Boolean.TRUE).build();
223         // SRP Mandatory in Upd
224         final SrpBuilder srpBuilder = new SrpBuilder();
225         // not sue whether use 0 instead of nextRequest() or do not insert srp == SRP-ID-number = 0
226         srpBuilder.setOperationId(nextRequest());
227         final Srp srp = srpBuilder.build();
228         //ERO Mandatory in Upd
229         final PathBuilder pb = new PathBuilder();
230         pb.setEro(new EroBuilder().build());
231
232         updBuilder.setPath(pb.build());
233         updBuilder.setLsp(lsp).setSrp(srp).setPath(pb.build());
234
235         pcupdMessageBuilder.setUpdates(Collections.singletonList(updBuilder.build()));
236         return srp.getOperationId();
237     }
238
239     @Holding("this")
240     private void markAllLspAsStale() {
241         staleLsps.addAll(lsps.keySet());
242     }
243
244     private boolean handleErrorMessage(final PcerrMessage message) {
245         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message
246                 .PcerrMessage errMsg = message.getPcerrMessage();
247         if (errMsg.getErrorType() instanceof StatefulCase) {
248             final StatefulCase stat = (StatefulCase) errMsg.getErrorType();
249             for (final Srps srps : stat.getStateful().getSrps()) {
250                 final SrpIdNumber id = srps.getSrp().getOperationId();
251                 if (id.getValue().toJava() != 0) {
252                     final PCEPRequest req = removeRequest(id);
253                     if (req != null) {
254                         req.done(OperationResults.createFailed(errMsg.getErrors()));
255                     } else {
256                         LOG.warn("Request ID {} not found in outstanding DB", id);
257                     }
258                 }
259             }
260         } else {
261             LOG.warn("Unhandled PCErr message {}.", errMsg);
262             return true;
263         }
264         return false;
265     }
266
267     private boolean isSolicited(final Srp srp, final Lsp lsp, final MessageContext ctx, final ReportedLspBuilder rlb) {
268         if (srp == null) {
269             return false;
270         }
271         final SrpIdNumber id = srp.getOperationId();
272         if (id.getValue().toJava() == 0) {
273             return false;
274         }
275         switch (lsp.getOperational()) {
276             case Active:
277             case Down:
278             case Up:
279                 if (!isTriggeredSyncInProcess()) {
280                     final PCEPRequest req = removeRequest(id);
281                     if (req != null) {
282                         LOG.debug("Request {} resulted in LSP operational state {}", id, lsp.getOperational());
283                         rlb.setMetadata(req.getMetadata());
284                         ctx.resolveRequest(req);
285                     } else {
286                         LOG.warn("Request ID {} not found in outstanding DB", id);
287                     }
288                 }
289                 break;
290             case GoingDown:
291             case GoingUp:
292                 // These are transitive states, so we don't have to do anything, as they will be followed
293                 // up...
294                 break;
295             default:
296                 break;
297         }
298         return true;
299     }
300
301     @Holding("this")
302     private boolean manageNextReport(final Reports report, final MessageContext ctx) {
303         final Lsp lsp = report.getLsp();
304         final PlspId plspid = lsp.getPlspId();
305         final Srp srp = report.getSrp();
306
307         if (!lsp.getSync() && (plspid == null || plspid.getValue().toJava() == 0)) {
308             purgeStaleLsps(ctx);
309             if (isTriggeredSyncInProcess()) {
310                 if (srp == null) {
311                     return false;
312                 }
313                 final SrpIdNumber id = srp.getOperationId();
314                 if (id.getValue().toJava() == 0) {
315                     return false;
316                 }
317                 final PCEPRequest req = removeRequest(id);
318                 ctx.resolveRequest(req);
319             }
320             stateSynchronizationAchieved(ctx);
321             return true;
322         }
323         final ReportedLspBuilder rlb = new ReportedLspBuilder();
324         boolean solicited = false;
325         solicited = isSolicited(srp, lsp, ctx, rlb);
326
327         // if remove flag is set in SRP object, remove the tunnel immediately
328         if (solicited) {
329             final Srp1 initiatedSrp = srp.augmentation(Srp1.class);
330             if (initiatedSrp != null && initiatedSrp.getRemove()) {
331                 super.removeLsp(ctx, plspid);
332                 return false;
333             }
334         }
335         rlb.setPath(BindingMap.of(buildPath(report, srp, lsp)));
336
337         String name = lookupLspName(plspid);
338         if (lsp.getTlvs() != null && lsp.getTlvs().getSymbolicPathName() != null) {
339             name = StandardCharsets.UTF_8.decode(ByteBuffer.wrap(lsp.getTlvs().getSymbolicPathName().getPathName()
340                     .getValue())).toString();
341         }
342         //get LspDB from LSP and write it to pcc's node
343         final LspDbVersion lspDbVersion = geLspDbVersionTlv(lsp);
344         if (lspDbVersion != null) {
345             updatePccNode(ctx, new PathComputationClientBuilder()
346                 .addAugmentation(new PathComputationClient1Builder().setLspDbVersion(lspDbVersion).build()).build());
347         }
348         updateLsp(ctx, plspid, name, rlb, solicited, lsp.getRemove());
349         unmarkStaleLsp(plspid);
350
351         LOG.debug("LSP {} updated", lsp);
352         return true;
353     }
354
355     private static Path buildPath(final Reports report, final Srp srp, final Lsp lsp) {
356         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.pcep.client
357                 .attributes.path.computation.client.reported.lsp.PathBuilder pb = new org.opendaylight.yang.gen.v1
358                 .urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.pcep.client.attributes.path.computation
359                 .client.reported.lsp.PathBuilder();
360         if (report.getPath() != null) {
361             pb.fieldsFrom(report.getPath());
362         }
363         // LSP is mandatory (if there is none, parser will throw an exception)
364         // this is to ensure a path will be created at any rate
365         final Path1Builder p1Builder = new Path1Builder();
366         p1Builder.setLsp(report.getLsp());
367         final PathSetupType pst;
368         if (srp != null && srp.getTlvs() != null && srp.getTlvs().getPathSetupType() != null) {
369             pst = srp.getTlvs().getPathSetupType();
370             p1Builder.setPathSetupType(pst);
371         } else {
372             pst = null;
373         }
374         pb.addAugmentation(p1Builder.build());
375         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp
376                 .object.lsp.Tlvs tlvs = report.getLsp().getTlvs();
377         if (tlvs != null) {
378             if (tlvs.getLspIdentifiers() != null) {
379                 pb.setLspId(tlvs.getLspIdentifiers().getLspId());
380             } else if (!PSTUtil.isDefaultPST(pst)) {
381                 pb.setLspId(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820
382                         .LspId(lsp.getPlspId().getValue()));
383             }
384         }
385         return pb.build();
386     }
387
388     private boolean handlePcreqMessage(final PcreqMessage message) {
389
390         LOG.info("Start PcRequest Message handler");
391
392         /* Get a Path Computation to compute the Path from the Request */
393         PathComputation pathComputation = pceServerProvider.getPathComputation();
394         Message rep = null;
395         /* Reply with Error Message if no valid Path Computation is available */
396         if (pathComputation == null) {
397             rep = createErrorMsg(PCEPErrors.RESOURCE_LIMIT_EXCEEDED, Uint32.ZERO);
398             sendMessage(rep, new SrpIdNumber(Uint32.ZERO), null);
399             return false;
400         }
401         for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq
402                 .message.Requests req : message.getRequests()) {
403             LOG.debug("Process request {}", req);
404             rep = pathComputation.computePath(req);
405             SrpIdNumber repId = null;
406             if (req.getRp() != null) {
407                 repId = new SrpIdNumber(req.getRp().getRequestId().getValue());
408             } else {
409                 repId = new SrpIdNumber(Uint32.ZERO);
410             }
411             sendMessage(rep, repId, null);
412         }
413         return false;
414     }
415
416     @Override
417     protected synchronized boolean onMessage(final MessageContext ctx, final Message message) {
418         if (message instanceof PcerrMessage) {
419             return handleErrorMessage((PcerrMessage) message);
420         }
421         if (message instanceof Pcreq) {
422             LOG.info("PcReq detected. Start Request Message handler");
423             return handlePcreqMessage(((Pcreq) message).getPcreqMessage());
424         }
425         if (!(message instanceof PcrptMessage)) {
426             return true;
427         }
428         listenerState.updateLastReceivedRptMsg();
429         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.pcrpt
430                 .message.PcrptMessage rpt = ((PcrptMessage) message).getPcrptMessage();
431         for (final Reports report : rpt.getReports()) {
432             if (!manageNextReport(report, ctx)) {
433                 return false;
434             }
435         }
436         return false;
437     }
438
439     private SrpIdNumber nextRequest() {
440         return new SrpIdNumber(Uint32.valueOf(requestId.getAndIncrement()));
441     }
442
443     @Override
444     @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH", justification = "SB does not grok TYPE_USE")
445     public synchronized ListenableFuture<OperationResult> addLsp(final AddLspArgs input) {
446         checkArgument(input != null && input.getName() != null && input.getNode() != null
447                 && input.getArguments() != null, MISSING_XML_TAG);
448         LOG.trace("AddLspArgs {}", input);
449         // Make sure there is no such LSP
450         final InstanceIdentifier<ReportedLsp> lsp = lspIdentifier(input.getName());
451         final ListenableFuture<Optional<ReportedLsp>> f = readOperationalData(lsp);
452         return f == null ? OperationResults.createUnsent(PCEPErrors.LSP_INTERNAL_ERROR).future()
453                 : Futures.transformAsync(f, new AddFunction(input, lsp), MoreExecutors.directExecutor());
454     }
455
456     @Override
457     @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH", justification = "SB does not grok TYPE_USE")
458     public synchronized ListenableFuture<OperationResult> removeLsp(final RemoveLspArgs input) {
459         checkArgument(input != null && input.getName() != null && input.getNode() != null, MISSING_XML_TAG);
460         LOG.trace("RemoveLspArgs {}", input);
461         // Make sure the LSP exists, we need it for PLSP-ID
462         final InstanceIdentifier<ReportedLsp> lsp = lspIdentifier(input.getName());
463         final ListenableFuture<Optional<ReportedLsp>> f = readOperationalData(lsp);
464         return f == null ? OperationResults.createUnsent(PCEPErrors.LSP_INTERNAL_ERROR).future()
465                 : Futures.transformAsync(f, rep -> {
466                     final Lsp reportedLsp = validateReportedLsp(rep, input);
467                     if (reportedLsp == null) {
468                         return OperationResults.createUnsent(PCEPErrors.UNKNOWN_PLSP_ID).future();
469                     }
470                     final PcinitiateMessageBuilder ib = new PcinitiateMessageBuilder(MESSAGE_HEADER);
471                     final Requests rb = buildRequest(rep, reportedLsp);
472                     ib.setRequests(Collections.singletonList(rb));
473                     return sendMessage(new PcinitiateBuilder().setPcinitiateMessage(ib.build()).build(),
474                         rb.getSrp().getOperationId(), null);
475                 }, MoreExecutors.directExecutor());
476     }
477
478     private Requests buildRequest(final Optional<ReportedLsp> rep, final Lsp reportedLsp) {
479         // Build the request and send it
480         final RequestsBuilder rb = new RequestsBuilder();
481         final SrpBuilder srpBuilder = new SrpBuilder().addAugmentation(new Srp1Builder()
482                 .setRemove(Boolean.TRUE).build()).setOperationId(nextRequest()).setProcessingRule(Boolean.TRUE);
483         final Optional<PathSetupType> maybePST = getPST(rep);
484         if (maybePST.isPresent()) {
485             srpBuilder.setTlvs(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful
486                     .rev200720.srp.object.srp.TlvsBuilder().setPathSetupType(maybePST.get()).build());
487         }
488         rb.setSrp(srpBuilder.build());
489         rb.setLsp(new LspBuilder().setRemove(Boolean.FALSE).setPlspId(reportedLsp.getPlspId())
490                 .setDelegate(reportedLsp.getDelegate()).build());
491         return rb.build();
492     }
493
494     @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
495             justification = "https://github.com/spotbugs/spotbugs/issues/811")
496     private ListenableFuture<OperationResult> redelegate(final Lsp reportedLsp, final Srp srp, final Lsp lsp,
497             final UpdateLspArgs input) {
498         // the D bit that was reported decides the type of PCE message sent
499         final boolean isDelegate = requireNonNull(reportedLsp.getDelegate());
500         final Message msg;
501         if (isDelegate) {
502             // we already have delegation, send update
503             final UpdatesBuilder rb = new UpdatesBuilder();
504             rb.setSrp(srp);
505             rb.setLsp(lsp);
506             final PathBuilder pb = new PathBuilder();
507             pb.fieldsFrom(input.getArguments());
508             rb.setPath(pb.build());
509             final PcupdMessageBuilder ub = new PcupdMessageBuilder(MESSAGE_HEADER);
510             ub.setUpdates(Collections.singletonList(rb.build()));
511             msg = new PcupdBuilder().setPcupdMessage(ub.build()).build();
512         } else {
513             final Lsp1 lspCreateFlag = reportedLsp.augmentation(Lsp1.class);
514             // we only retake delegation for PCE initiated tunnels
515             if (lspCreateFlag != null && !lspCreateFlag.getCreate()) {
516                 LOG.warn("Unable to retake delegation of PCC-initiated tunnel: {}", reportedLsp);
517                 return OperationResults.createUnsent(PCEPErrors.UPDATE_REQ_FOR_NON_LSP).future();
518             }
519             // we want to revoke delegation, different type of message
520             // is sent because of specification by Siva
521             // this message is also sent, when input delegate bit is set to 0
522             // generating an error in PCC
523             final List<Requests> reqs = new ArrayList<>();
524             reqs.add(new RequestsBuilder().setSrp(srp).setLsp(lsp).build());
525             final PcinitiateMessageBuilder ib = new PcinitiateMessageBuilder();
526             ib.setRequests(reqs);
527             msg = new PcinitiateBuilder().setPcinitiateMessage(ib.build()).build();
528         }
529         return sendMessage(msg, srp.getOperationId(), input.getArguments().getMetadata());
530     }
531
532     @Override
533     @SuppressFBWarnings(value = "NP_NULL_ON_SOME_PATH", justification = "SB does not grok TYPE_USE")
534
535     public synchronized ListenableFuture<OperationResult> updateLsp(final UpdateLspArgs input) {
536         checkArgument(input != null && input.getName() != null && input.getNode() != null
537                 && input.getArguments() != null, MISSING_XML_TAG);
538         LOG.trace("UpdateLspArgs {}", input);
539         // Make sure the LSP exists
540         final InstanceIdentifier<ReportedLsp> lsp = lspIdentifier(input.getName());
541         final ListenableFuture<Optional<ReportedLsp>> f = readOperationalData(lsp);
542         return f == null ? OperationResults.createUnsent(PCEPErrors.LSP_INTERNAL_ERROR).future()
543                 : Futures.transformAsync(f, new UpdateFunction(input), MoreExecutors.directExecutor());
544     }
545
546     @Override
547     public synchronized ListenableFuture<OperationResult> ensureLspOperational(final EnsureLspOperationalInput input) {
548         checkArgument(input != null && input.getName() != null && input.getNode() != null, MISSING_XML_TAG);
549         final Arguments args = input.getArguments();
550         checkArgument(args != null, MISSING_XML_TAG);
551
552         final OperationalStatus op;
553         final Arguments1 aa = args.augmentation(Arguments1.class);
554         if (aa != null) {
555             op = aa.getOperational();
556         } else {
557             op = null;
558         }
559
560         // Make sure the LSP exists
561         final InstanceIdentifier<ReportedLsp> lsp = lspIdentifier(input.getName());
562         LOG.debug("Checking if LSP {} has operational state {}", lsp, op);
563         final ListenableFuture<Optional<ReportedLsp>> f = readOperationalData(lsp);
564         return f == null ? OperationResults.createUnsent(PCEPErrors.LSP_INTERNAL_ERROR).future()
565                 : listenableFuture(f, input, op);
566     }
567
568     private static ListenableFuture<OperationResult> listenableFuture(
569             final ListenableFuture<Optional<ReportedLsp>> future, final EnsureLspOperationalInput input,
570             final OperationalStatus op) {
571         return Futures.transform(future, rep -> {
572             if (!rep.isPresent()) {
573                 LOG.debug("Node {} does not contain LSP {}", input.getNode(), input.getName());
574                 return OperationResults.UNSENT;
575             }
576             // check if at least one of the paths has the same status as requested
577             for (final Path p : rep.get().nonnullPath().values()) {
578                 final Path1 p1 = p.augmentation(Path1.class);
579                 if (p1 == null) {
580                     LOG.warn("Node {} LSP {} does not contain data", input.getNode(), input.getName());
581                     return OperationResults.UNSENT;
582                 }
583                 if (op.equals(p1.getLsp().getOperational())) {
584                     return OperationResults.SUCCESS;
585                 }
586             }
587             return OperationResults.UNSENT;
588         }, MoreExecutors.directExecutor());
589     }
590
591     @Override
592     protected Lsp validateReportedLsp(final Optional<ReportedLsp> rep, final LspId input) {
593         if (!rep.isPresent()) {
594             LOG.debug("Node {} does not contain LSP {}", input.getNode(), input.getName());
595             return null;
596         }
597         // it doesn't matter how many lsps there are in the path list, we only need data that is the same in each path
598         final Path1 ra = rep.get().getPath().values().iterator().next().augmentation(Path1.class);
599         checkState(ra != null, "Reported LSP reported null from data-store.");
600         final Lsp reportedLsp = ra.getLsp();
601         checkState(reportedLsp != null, "Reported LSP does not contain LSP object.");
602         return reportedLsp;
603     }
604
605     private static Optional<PathSetupType> getPST(final Optional<ReportedLsp> rep) {
606         if (rep.isPresent()) {
607             final Path1 path1 = rep.get().getPath().values().iterator().next().augmentation(Path1.class);
608             if (path1 != null) {
609                 final PathSetupType pst = path1.getPathSetupType();
610                 if (!PSTUtil.isDefaultPST(pst)) {
611                     return Optional.of(pst);
612                 }
613             }
614         }
615         return Optional.empty();
616     }
617
618     /**
619      * Recover lspData and mark any LSPs in the LSP database that were previously reported by the PCC as stale.
620      */
621     @Override
622     protected synchronized void loadLspData(final Node node, final Map<String, ReportedLsp> lspData,
623             final Map<PlspId, String> lsps, final boolean incrementalSynchro) {
624         //load node's lsps from DS
625         final PathComputationClient pcc = node.augmentation(Node1.class).getPathComputationClient();
626         for (final ReportedLsp reportedLsp : pcc.nonnullReportedLsp().values()) {
627             final String lspName = reportedLsp.getName();
628             lspData.put(lspName, reportedLsp);
629             if (!reportedLsp.getPath().isEmpty()) {
630                 final Path1 path1 = reportedLsp.getPath().values().iterator().next().augmentation(Path1.class);
631                 if (path1 != null) {
632                     final PlspId plspId = path1.getLsp().getPlspId();
633                     if (!incrementalSynchro) {
634                         staleLsps.add(plspId);
635                     }
636                     lsps.put(plspId, lspName);
637                 }
638             }
639         }
640     }
641
642     /**
643      * When the PCC reports an LSP during state synchronization, if the LSP already
644      * exists in the LSP database, the PCE MUST update the LSP database and
645      * clear the stale marker from the LSP.
646      *
647      * @param plspId id
648      */
649     private synchronized void unmarkStaleLsp(final PlspId plspId) {
650         staleLsps.remove(plspId);
651     }
652
653     /**
654      * Purge any LSPs from the LSP database that are still marked as stale.
655      *
656      * @param ctx message context
657      */
658     private synchronized void purgeStaleLsps(final MessageContext ctx) {
659         for (final PlspId plspId : staleLsps) {
660             removeLsp(ctx, plspId);
661         }
662         staleLsps.clear();
663     }
664
665     @Override
666     public boolean isInitiationCapability() {
667         return initiationCapability.get();
668     }
669
670     @Override
671     public boolean isStatefulCapability() {
672         return statefulCapability.get();
673     }
674
675     @Override
676     public boolean isLspUpdateCapability() {
677         return lspUpdateCapability.get();
678     }
679
680     private synchronized void setStatefulCapabilities(final Stateful stateful) {
681         statefulCapability.set(true);
682         if (stateful.getLspUpdateCapability() != null) {
683             lspUpdateCapability.set(stateful.getLspUpdateCapability());
684         }
685         final Stateful1 stateful1 = stateful.augmentation(Stateful1.class);
686         if (stateful1 != null && stateful1.getInitiation() != null) {
687             initiationCapability.set(stateful1.getInitiation());
688         }
689     }
690
691     private class ResyncLspFunction implements AsyncFunction<Optional<ReportedLsp>, OperationResult> {
692
693         private final TriggerSyncArgs input;
694
695         ResyncLspFunction(final TriggerSyncArgs input) {
696             this.input = input;
697         }
698
699         @Override
700         public ListenableFuture<OperationResult> apply(final Optional<ReportedLsp> rep) {
701             final Lsp reportedLsp = validateReportedLsp(rep, input);
702             if (reportedLsp == null || !rep.isPresent()) {
703                 return OperationResults.createUnsent(PCEPErrors.UNKNOWN_PLSP_ID).future();
704             }
705             // mark lsp as stale
706             final ReportedLsp staleLsp = rep.get();
707             if (!staleLsp.getPath().isEmpty()) {
708                 final Path1 path1 = staleLsp.getPath().values().iterator().next().augmentation(Path1.class);
709                 if (path1 != null) {
710                     staleLsps.add(path1.getLsp().getPlspId());
711                 }
712             }
713             updatePccState(PccSyncState.PcepTriggeredResync);
714             // create PCUpd with mandatory objects and LSP object set to 1
715             final SrpBuilder srpBuilder = new SrpBuilder();
716             srpBuilder.setOperationId(nextRequest());
717             srpBuilder.setProcessingRule(Boolean.TRUE);
718
719             final Optional<PathSetupType> maybePST = getPST(rep);
720             if (maybePST.isPresent()) {
721                 srpBuilder.setTlvs(
722                         new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful
723                                 .rev200720.srp.object.srp.TlvsBuilder()
724                                 .setPathSetupType(maybePST.get()).build());
725             }
726
727             final Srp srp = srpBuilder.build();
728             final Lsp lsp = new LspBuilder().setPlspId(reportedLsp.getPlspId()).setSync(Boolean.TRUE).build();
729
730             final Message msg = createPcepUpd(srp, lsp);
731             return sendMessage(msg, srp.getOperationId(), null);
732         }
733
734         private Message createPcepUpd(final Srp srp, final Lsp lsp) {
735             final UpdatesBuilder rb = new UpdatesBuilder();
736             rb.setSrp(srp);
737             rb.setLsp(lsp);
738             final PathBuilder pb = new PathBuilder();
739             rb.setPath(pb.build());
740             final PcupdMessageBuilder ub = new PcupdMessageBuilder(MESSAGE_HEADER);
741             ub.setUpdates(Collections.singletonList(rb.build()));
742             return new PcupdBuilder().setPcupdMessage(ub.build()).build();
743         }
744     }
745
746     private class AddFunction implements AsyncFunction<Optional<ReportedLsp>, OperationResult> {
747
748         private final AddLspArgs input;
749         private final InstanceIdentifier<ReportedLsp> lsp;
750
751         AddFunction(final AddLspArgs input, final InstanceIdentifier<ReportedLsp> lsp) {
752             this.input = input;
753             this.lsp = lsp;
754         }
755
756         @Override
757         public ListenableFuture<OperationResult> apply(final Optional<ReportedLsp> rep) {
758             if (rep.isPresent()) {
759                 LOG.debug("Node {} already contains lsp {} at {}", input.getNode(), input.getName(), lsp);
760                 return OperationResults.createUnsent(PCEPErrors.USED_SYMBOLIC_PATH_NAME).future();
761             }
762             if (!initiationCapability.get()) {
763                 return OperationResults.createUnsent(PCEPErrors.CAPABILITY_NOT_SUPPORTED).future();
764             }
765
766             // Build the request
767             final RequestsBuilder rb = new RequestsBuilder();
768             final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120
769                     .add.lsp.args.Arguments args = input.getArguments();
770             final Arguments2 args2 = args.augmentation(Arguments2.class);
771             final Lsp inputLsp = args2 != null ? args2.getLsp() : null;
772             if (inputLsp == null) {
773                 return OperationResults.createUnsent(PCEPErrors.LSP_MISSING).future();
774             }
775
776             rb.fieldsFrom(input.getArguments());
777
778             /* Call Path Computation if an ERO was not provided */
779             boolean segmentRouting = !PSTUtil.isDefaultPST(args2.getPathSetupType());
780             if (rb.getEro() == null
781                     || rb.getEro().getSubobject() == null
782                     || rb.getEro().getSubobject().size() == 0) {
783
784                 /* Get a Path Computation to compute the Path from the Arguments */
785                 PathComputation pathComputation = pceServerProvider.getPathComputation();
786                 if (pathComputation == null) {
787                     return OperationResults.createUnsent(PCEPErrors.ERO_MISSING).future();
788                 }
789                 rb.setEro(pathComputation.computeEro(args.getEndpointsObj(), args.getBandwidth(), args.getClassType(),
790                         args.getMetrics(), segmentRouting));
791             }
792
793             final TlvsBuilder tlvsBuilder;
794             if (inputLsp.getTlvs() != null) {
795                 tlvsBuilder = new TlvsBuilder(inputLsp.getTlvs());
796             } else {
797                 tlvsBuilder = new TlvsBuilder();
798             }
799             tlvsBuilder.setSymbolicPathName(
800                     new SymbolicPathNameBuilder().setPathName(new SymbolicPathName(input.getName()
801                             .getBytes(StandardCharsets.UTF_8))).build());
802
803             final SrpBuilder srpBuilder = new SrpBuilder()
804                     .setOperationId(nextRequest())
805                     .setProcessingRule(Boolean.TRUE);
806             if (segmentRouting) {
807                 srpBuilder.setTlvs(
808                         new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf
809                                 .stateful.rev200720.srp.object.srp.TlvsBuilder()
810                                 .setPathSetupType(args2.getPathSetupType()).build());
811             }
812             rb.setSrp(srpBuilder.build());
813
814             rb.setLsp(new LspBuilder()
815                 .setAdministrative(inputLsp.getAdministrative())
816                 .setDelegate(inputLsp.getDelegate())
817                 .setPlspId(PLSPID_ZERO)
818                 .setTlvs(tlvsBuilder.build())
819                 .build());
820
821             // Send the message
822             return sendMessage(new PcinitiateBuilder()
823                 .setPcinitiateMessage(new PcinitiateMessageBuilder(MESSAGE_HEADER)
824                     .setRequests(Collections.singletonList(rb.build()))
825                     .build())
826                 .build(),
827                 rb.getSrp().getOperationId(), input.getArguments().getMetadata());
828         }
829     }
830
831     private class UpdateFunction implements AsyncFunction<Optional<ReportedLsp>, OperationResult> {
832
833         private final UpdateLspArgs input;
834
835         UpdateFunction(final UpdateLspArgs input) {
836             this.input = input;
837         }
838
839         @Override
840         public ListenableFuture<OperationResult> apply(final Optional<ReportedLsp> rep) {
841             final Lsp reportedLsp = validateReportedLsp(rep, input);
842             if (reportedLsp == null) {
843                 return OperationResults.createUnsent(PCEPErrors.UNKNOWN_PLSP_ID).future();
844             }
845             // create mandatory objects
846             final Arguments3 args = input.getArguments().augmentation(Arguments3.class);
847             final SrpBuilder srpBuilder = new SrpBuilder();
848             srpBuilder.setOperationId(nextRequest());
849             srpBuilder.setProcessingRule(Boolean.TRUE);
850             if (args != null && args.getPathSetupType() != null) {
851                 if (!PSTUtil.isDefaultPST(args.getPathSetupType())) {
852                     srpBuilder.setTlvs(
853                             new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful
854                                     .rev200720.srp.object.srp.TlvsBuilder()
855                                     .setPathSetupType(args.getPathSetupType()).build());
856                 }
857             } else {
858                 final Optional<PathSetupType> maybePST = getPST(rep);
859                 if (maybePST.isPresent()) {
860                     srpBuilder.setTlvs(
861                             new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful
862                                     .rev200720.srp.object.srp.TlvsBuilder()
863                                     .setPathSetupType(maybePST.get()).build());
864                 }
865             }
866             final Srp srp = srpBuilder.build();
867             final Lsp inputLsp = args != null ? args.getLsp() : null;
868             final LspBuilder lspBuilder = new LspBuilder().setPlspId(reportedLsp.getPlspId());
869             if (inputLsp != null) {
870                 lspBuilder.setDelegate(Boolean.TRUE.equals(inputLsp.getDelegate()))
871                         .setTlvs(inputLsp.getTlvs())
872                         .setAdministrative(Boolean.TRUE.equals(inputLsp.getAdministrative()));
873             }
874             return redelegate(reportedLsp, srp, lspBuilder.build(), input);
875         }
876     }
877
878     private static Pcerr createErrorMsg(@NonNull final PCEPErrors pcepErrors, final Uint32 reqID) {
879         return new PcerrBuilder()
880                 .setPcerrMessage(new PcerrMessageBuilder()
881                     .setErrorType(new RequestCaseBuilder()
882                         .setRequest(new RequestBuilder()
883                             .setRps(Collections.singletonList(new RpsBuilder()
884                                 .setRp(new RpBuilder()
885                                     .setProcessingRule(false)
886                                     .setIgnore(false)
887                                     .setRequestId(new RequestId(reqID))
888                                     .build())
889                                 .build()))
890                             .build())
891                         .build())
892                     .setErrors(Collections.singletonList(new ErrorsBuilder()
893                         .setErrorObject(new ErrorObjectBuilder()
894                             .setType(pcepErrors.getErrorType())
895                             .setValue(pcepErrors.getErrorValue())
896                             .build())
897                         .build()))
898                     .build())
899                 .build();
900     }
901 }