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