Replace Preconditions.CheckNotNull per RequireNonNull
[bgpcep.git] / pcep / pcc-mock / src / main / java / org / opendaylight / protocol / pcep / pcc / mock / PCCTunnelManagerImpl.java
1 /*
2  * Copyright (c) 2015 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
9 package org.opendaylight.protocol.pcep.pcc.mock;
10
11 import static java.util.Objects.requireNonNull;
12 import static org.opendaylight.protocol.pcep.pcc.mock.spi.MsgBuilderUtil.createLsp;
13 import static org.opendaylight.protocol.pcep.pcc.mock.spi.MsgBuilderUtil.createLspTlvs;
14 import static org.opendaylight.protocol.pcep.pcc.mock.spi.MsgBuilderUtil.createLspTlvsEndofSync;
15 import static org.opendaylight.protocol.pcep.pcc.mock.spi.MsgBuilderUtil.createPath;
16 import static org.opendaylight.protocol.pcep.pcc.mock.spi.MsgBuilderUtil.createPcRtpMessage;
17 import static org.opendaylight.protocol.pcep.pcc.mock.spi.MsgBuilderUtil.createSrp;
18 import static org.opendaylight.protocol.pcep.pcc.mock.spi.MsgBuilderUtil.reqToRptPath;
19 import static org.opendaylight.protocol.pcep.pcc.mock.spi.MsgBuilderUtil.updToRptPath;
20
21 import com.google.common.base.Optional;
22 import com.google.common.base.Preconditions;
23 import com.google.common.net.InetAddresses;
24 import io.netty.util.Timeout;
25 import io.netty.util.Timer;
26 import java.math.BigInteger;
27 import java.net.InetAddress;
28 import java.util.Collections;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Map.Entry;
33 import java.util.concurrent.TimeUnit;
34 import java.util.concurrent.atomic.AtomicLong;
35 import javax.annotation.Nonnull;
36 import javax.annotation.concurrent.GuardedBy;
37 import org.opendaylight.protocol.pcep.pcc.mock.api.LspType;
38 import org.opendaylight.protocol.pcep.pcc.mock.api.PCCSession;
39 import org.opendaylight.protocol.pcep.pcc.mock.api.PCCTunnelManager;
40 import org.opendaylight.protocol.pcep.pcc.mock.spi.MsgBuilderUtil;
41 import org.opendaylight.protocol.pcep.spi.PCEPErrors;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Lsp1;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Lsp1Builder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.Srp1Builder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.crabbe.initiated.rev131126.pcinitiate.message.pcinitiate.message.Requests;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.OperationalStatus;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Pcrpt;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.PlspId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.SrpIdNumber;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.Lsp;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.LspBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.pcrpt.message.reports.Path;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcrpt.message.pcrpt.message.reports.PathBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.pcupd.message.pcupd.message.Updates;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.Srp;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.srp.object.SrpBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.explicit.route.object.ero.Subobject;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.IpPrefixCase;
61
62 public final class PCCTunnelManagerImpl implements PCCTunnelManager {
63
64     private static final Optional<Srp> NO_SRP = Optional.absent();
65     @GuardedBy("this")
66     private final Map<Integer, PCCSession> sessions = new HashMap<>();
67     private final AtomicLong plspIDsCounter;
68     private final String address;
69     private final Timer timer;
70     private final int redelegationTimeout;
71     private final int stateTimeout;
72     private final int lspsCount;
73     private final Optional<TimerHandler> timerHandler;
74     @GuardedBy("this")
75     private final Map<PlspId, PCCTunnel> tunnels = new HashMap<>();
76     private PCCSyncOptimization syncOptimization;
77
78     public PCCTunnelManagerImpl(final int lspsCount, final InetAddress address, final int redelegationTimeout,
79                                 final int stateTimeout, final Timer timer, final Optional<TimerHandler> timerHandler) {
80         Preconditions.checkArgument(lspsCount >= 0);
81         this.redelegationTimeout = redelegationTimeout;
82         this.stateTimeout = stateTimeout;
83         this.plspIDsCounter = new AtomicLong(lspsCount);
84         this.address = InetAddresses.toAddrString(requireNonNull(address));
85         this.timer = requireNonNull(timer);
86         this.timerHandler = timerHandler;
87         this.lspsCount = lspsCount;
88     }
89
90     protected void reportToAll(final Updates update, final PCCSession session) {
91         final PlspId plspId = update.getLsp().getPlspId();
92         final PCCTunnel tunnel = this.tunnels.get(plspId);
93         final long srpId = update.getSrp().getOperationId().getValue();
94         if (tunnel != null) {
95             if (hasDelegation(tunnel, session)) {
96                 final Srp srp = createSrp(update.getSrp().getOperationId().getValue());
97                 final Path path = updToRptPath(update.getPath());
98                 final List<Subobject> subobjects = update.getPath().getEro().getSubobject();
99                 final Lsp lsp = update.getLsp();
100                 sendToAll(tunnel, plspId, subobjects, srp, path, lsp);
101                 //update tunnel state
102                 tunnel.setLspState(path);
103             } else {
104                 session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, srpId));
105             }
106         } else {
107             session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
108         }
109     }
110
111     private void returnDelegation(final Updates update, final PCCSession session) {
112         final PlspId plspId = update.getLsp().getPlspId();
113         final PCCTunnel tunnel = this.tunnels.get(plspId);
114         final long srpId = update.getSrp().getOperationId().getValue();
115         if (tunnel != null) {
116             //check if session really has a delegation
117             if (hasDelegation(tunnel, session)) {
118                 //send report D=0
119                 final Tlvs tlvs = buildTlvs(tunnel, plspId.getValue(), Optional.absent());
120                 final Pcrpt pcrtp = createPcRtpMessage(new LspBuilder(update.getLsp()).setSync(true).setOperational(OperationalStatus.Up).setDelegate(false).
121                     setTlvs(tlvs).build(), Optional.of(createSrp(srpId)), tunnel.getLspState());
122                 session.sendReport(pcrtp);
123                 //start state timer
124                 startStateTimeout(tunnel, plspId);
125                 //if PCC's LSP, start re-delegation timer
126                 if (tunnel.getType() == LspType.PCC_LSP) {
127                     startRedelegationTimer(tunnel, plspId, session);
128                 } else {
129                     //if PCE-initiated LSP, revoke delegation instantly
130                     setDelegation(plspId, null);
131                 }
132             } else {
133                 session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, srpId));
134             }
135         } else {
136             session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
137         }
138     }
139
140     protected void takeDelegation(final Requests request, final PCCSession session) {
141         final PlspId plspId = request.getLsp().getPlspId();
142         final PCCTunnel tunnel = this.tunnels.get(plspId);
143         final long srpId = request.getSrp().getOperationId().getValue();
144         if (tunnel != null) {
145             //check if tunnel has no delegation
146             if ((tunnel.getType() == LspType.PCE_LSP) && ((tunnel.getDelegationHolder() == -1) || (tunnel.getDelegationHolder() == session.getId()))) {
147                 //set delegation
148                 tunnel.cancelTimeouts();
149                 setDelegation(plspId, session);
150                 //send report
151                 final Tlvs tlvs = buildTlvs(tunnel, plspId.getValue(), Optional.absent());
152                 session.sendReport(createPcRtpMessage(
153                     new LspBuilder(request.getLsp()).setSync(true).setOperational(OperationalStatus.Up).setDelegate(true).setTlvs(tlvs).build(),
154                     Optional.of(createSrp(srpId)), tunnel.getLspState()));
155             } else {
156                 session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.LSP_NOT_PCE_INITIATED, srpId));
157             }
158         } else {
159             session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
160         }
161     }
162
163     @Override
164     public synchronized void onSessionUp(final PCCSession session) {
165         this.syncOptimization = new PCCSyncOptimization(session);
166         lazyTunnelInicialization();
167
168         //first session - delegate all PCC's LSPs only when reporting at startup
169         if (!this.sessions.containsKey(session.getId()) && (session.getId() == 0)) {
170             for (final PlspId plspId : this.tunnels.keySet()) {
171                 setDelegation(plspId, session);
172             }
173         }
174         this.sessions.put(session.getId(), session);
175
176         if (!this.syncOptimization.isTriggeredInitSyncEnabled()) {
177             lspReport(session);
178         }
179     }
180
181     @Override
182     public synchronized void onSessionDown(final PCCSession session) {
183         for (final Entry<PlspId, PCCTunnel> entry : this.tunnels.entrySet()) {
184             final PCCTunnel tunnel = entry.getValue();
185             final PlspId plspId = entry.getKey();
186             //deal with delegations
187             if (hasDelegation(tunnel, session)) {
188                 startStateTimeout(tunnel, entry.getKey());
189                 startRedelegationTimer(tunnel, plspId, session);
190             }
191         }
192     }
193
194     protected void addTunnel(final Requests request, final PCCSession session) {
195         final PlspId plspId = new PlspId(this.plspIDsCounter.incrementAndGet());
196         final PCCTunnel tunnel = new PCCTunnel(request.getLsp().getTlvs().getSymbolicPathName().getPathName().getValue(),
197             session.getId(), LspType.PCE_LSP, reqToRptPath(request));
198         sendToAll(tunnel, plspId, request.getEro().getSubobject(), createSrp(request.getSrp().getOperationId().getValue()),
199             tunnel.getLspState(), new LspBuilder(request.getLsp()).addAugmentation(Lsp1.class, new Lsp1Builder().setCreate(true).build()).build());
200         this.tunnels.put(plspId, tunnel);
201     }
202
203     protected void removeTunnel(final Requests request, final PCCSession session) {
204         final PlspId plspId = request.getLsp().getPlspId();
205         final PCCTunnel tunnel = this.tunnels.get(plspId);
206         final long srpId = request.getSrp().getOperationId().getValue();
207         if (tunnel != null) {
208             if (tunnel.getType() == LspType.PCE_LSP) {
209                 if (hasDelegation(tunnel, session)) {
210                     this.tunnels.remove(plspId);
211                     sendToAll(tunnel, plspId, tunnel.getLspState().getEro().getSubobject(),
212                         new SrpBuilder(request.getSrp()).addAugmentation(Srp1.class, new Srp1Builder().setRemove(true).build()).build(),
213                         reqToRptPath(request), request.getLsp());
214                 } else {
215                     session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UPDATE_REQ_FOR_NON_LSP, srpId));
216                 }
217             } else {
218                 session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.LSP_NOT_PCE_INITIATED, srpId));
219             }
220         } else {
221             session.sendError(MsgBuilderUtil.createErrorMsg(PCEPErrors.UNKNOWN_PLSP_ID, srpId));
222         }
223     }
224
225     @Override
226     public void onMessagePcupd(@Nonnull final Updates update, @Nonnull final PCCSession session) {
227         final Lsp lsp = update.getLsp();
228         if (isInitialSyncTriggered(lsp)) {
229             lspReport(session);
230             if (this.timerHandler.isPresent()) {
231                 this.timerHandler.get().createDisconnectTask();
232             }
233         } else if (isReSyncTriggered(lsp)) {
234             handledDbTriggeredResync(update, session);
235         } else if ((lsp.isDelegate() != null) && lsp.isDelegate()) {
236             //regular LSP update
237             reportToAll(update, session);
238         } else {
239             //returning LSP delegation
240             returnDelegation(update, session);
241         }
242     }
243
244     @Override
245     public void onMessagePcInitiate(@Nonnull final Requests request, @Nonnull final PCCSession session) {
246         if ((request.getSrp().getAugmentation(Srp1.class) != null) && request.getSrp().getAugmentation(Srp1.class).isRemove()) {
247             //remove LSP
248             removeTunnel(request, session);
249         } else if ((request.getLsp().isDelegate() != null) && request.getLsp().isDelegate() && (request.getEndpointsObj() == null)) {
250             //take LSP delegation
251             takeDelegation(request, session);
252         } else {
253             //create LSP
254             addTunnel(request, session);
255         }
256     }
257
258     private Tlvs buildTlvs(final PCCTunnel tunnel, final Long plspId, final Optional<List<Subobject>> subobjectsList) {
259         final List<Subobject> subObject = subobjectsList.isPresent() ? subobjectsList.get() : tunnel.getLspState().getEro().getSubobject();
260         final String destinationAddress = getDestinationAddress(subObject, this.address);
261
262         return createLspTlvs(plspId, true, destinationAddress, this.address, this.address, Optional.of(tunnel.getPathName()),
263             this.syncOptimization.incrementLspDBVersion());
264     }
265
266     private void lazyTunnelInicialization() {
267         if (this.tunnels.isEmpty()) {
268             final BigInteger dbV = this.syncOptimization.getLocalLspDbVersionValue();
269             if (this.syncOptimization.isSyncAvoidanceEnabled() && !((dbV != null) && dbV.equals(BigInteger.ONE))) {
270                 this.tunnels.putAll(PCCTunnelBuilder.createTunnels(this.address, dbV.intValue()));
271             } else {
272                 this.tunnels.putAll(PCCTunnelBuilder.createTunnels(this.address, this.lspsCount));
273             }
274         }
275     }
276
277     private boolean isReSyncTriggered(final Lsp lsp) {
278         return this.syncOptimization.isTriggeredReSyncEnabled() && lsp.isSync();
279     }
280
281     private boolean isInitialSyncTriggered(final Lsp lsp) {
282         return (lsp.getPlspId().getValue() == 0) && lsp.isSync() && this.syncOptimization.isTriggeredInitSyncEnabled();
283     }
284
285     private void handledDbTriggeredResync(final Updates update, final PCCSession session) {
286         this.syncOptimization.setResynchronizingState(Boolean.TRUE);
287         final SrpIdNumber operationId = update.getSrp().getOperationId();
288         if (update.getLsp().getPlspId().getValue() == 0) {
289             reportAllKnownLsp(Optional.of(operationId), session);
290         } else {
291             reportLsp(update.getLsp().getPlspId(), operationId, session);
292         }
293         sendEndOfSynchronization(session, Optional.of(operationId));
294         this.syncOptimization.setResynchronizingState(Boolean.FALSE);
295     }
296
297     private void lspReport(final PCCSession session) {
298         if (!this.tunnels.isEmpty()) {
299             if (!this.syncOptimization.isSyncAvoidanceEnabled()) {
300                 reportAllKnownLsp(session);
301                 sendEndOfSynchronization(session);
302             } else if (!this.syncOptimization.doesLspDbMatch()) {
303                 if (this.syncOptimization.isDeltaSyncEnabled()) {
304                     reportMissedLsp(session);
305                     sendEndOfSynchronization(session);
306                 } else {
307                     reportAllKnownLsp(session);
308                     sendEndOfSynchronization(session);
309                 }
310             }
311         }
312     }
313
314     /**
315      * Reports Missed Lsp when DbVersion doesnt match
316      *
317      * @param session
318      */
319     private void reportMissedLsp(final PCCSession session) {
320         for (long missedLsp = this.syncOptimization.getRemoteLspDbVersionValue().longValue() + 1;
321              missedLsp <= this.syncOptimization.getLocalLspDbVersionValue().longValue(); missedLsp++) {
322             final PlspId plspId = new PlspId(missedLsp);
323             final PCCTunnel tunnel = this.tunnels.get(plspId);
324             createLspAndSendReport(missedLsp, tunnel, session, Optional.absent(), NO_SRP);
325         }
326     }
327
328     private void createLspAndSendReport(final long plspId, final PCCTunnel tunnel, final PCCSession session, final Optional<Boolean> isSync, final Optional<Srp> srp) {
329         final boolean delegation = hasDelegation(tunnel, session);
330         if (delegation) {
331             tunnel.cancelTimeouts();
332         }
333         final String destinationAddress = getDestinationAddress(tunnel.getLspState().getEro().getSubobject(), this.address);
334         final Tlvs tlvs = createLspTlvs(plspId, true, destinationAddress, this.address, this.address, Optional.of(tunnel.getPathName()),
335             this.syncOptimization.incrementLspDBVersion());
336
337         final boolean sync = isSync.isPresent() ? isSync.get() : this.syncOptimization.isSyncNeedIt();
338         final Lsp lsp = createLsp(plspId, sync, Optional.fromNullable(tlvs), delegation, false);
339         final Pcrpt pcrtp = createPcRtpMessage(lsp, srp, tunnel.getLspState());
340         session.sendReport(pcrtp);
341     }
342
343     private void sendEndOfSynchronization(final PCCSession session) {
344         sendEndOfSynchronization(session, Optional.absent());
345     }
346
347     private void sendEndOfSynchronization(final PCCSession session, final Optional<SrpIdNumber> operationId) {
348         Srp srp = null;
349         if (operationId.isPresent()) {
350             srp = new SrpBuilder().setOperationId(operationId.get()).build();
351         }
352         Optional<Tlvs> tlv = Optional.absent();
353         if (this.syncOptimization.isSyncAvoidanceEnabled()) {
354             tlv = createLspTlvsEndofSync(this.syncOptimization.incrementLspDBVersion().get());
355         }
356         final Pcrpt pcrtp = createPcRtpMessage(createLsp(0, false, tlv, true, false), Optional.fromNullable(srp), createPath(Collections
357             .emptyList()));
358         session.sendReport(pcrtp);
359     }
360
361     private void reportAllKnownLsp(final PCCSession session) {
362         reportAllKnownLsp(Optional.absent(), session);
363     }
364
365     private void reportAllKnownLsp(final Optional<SrpIdNumber> operationId, final PCCSession session) {
366         Srp srp = null;
367         if (operationId.isPresent()) {
368             srp = new SrpBuilder().setOperationId(operationId.get()).build();
369         }
370
371         for (final Entry<PlspId, PCCTunnel> entry : this.tunnels.entrySet()) {
372             final PCCTunnel tunnel = entry.getValue();
373             final long plspId = entry.getKey().getValue();
374             createLspAndSendReport(plspId, tunnel, session, Optional.absent(), Optional.fromNullable(srp));
375         }
376     }
377
378     private void reportLsp(final PlspId plspId, final SrpIdNumber operationId, final PCCSession session) {
379         final PCCTunnel tunnel = this.tunnels.get(plspId);
380         if (tunnel == null) {
381             return;
382         }
383         final Srp srp = new SrpBuilder().setOperationId(operationId).build();
384         createLspAndSendReport(plspId.getValue(), tunnel, session, Optional.of(Boolean.TRUE), Optional.of(srp));
385     }
386
387     private void sendToAll(final PCCTunnel tunnel, final PlspId plspId, final List<Subobject> subobjects, final Srp srp, final Path path, final Lsp lsp) {
388         for (final PCCSession session : this.sessions.values()) {
389             final boolean isDelegated = hasDelegation(tunnel, session);
390             final Tlvs tlvs = buildTlvs(tunnel, plspId.getValue(), Optional.of(subobjects));
391
392             final Pcrpt pcRpt = createPcRtpMessage(
393                 new LspBuilder(lsp)
394                     .setPlspId(plspId)
395                     .setOperational(OperationalStatus.Up)
396                     .setDelegate(isDelegated)
397                     .setSync(true)
398                     .addAugmentation(Lsp1.class, new Lsp1Builder().setCreate(tunnel.getType() == LspType.PCE_LSP).build())
399                     .setTlvs(tlvs).build(),
400                 Optional.fromNullable(srp), path);
401             session.sendReport(pcRpt);
402         }
403     }
404
405     private void startStateTimeout(final PCCTunnel tunnel, final PlspId plspId) {
406         if (this.stateTimeout > -1) {
407             final Timeout newStateTimeout = this.timer.newTimeout(timeout -> {
408                 if (tunnel.getType() == LspType.PCE_LSP) {
409                     PCCTunnelManagerImpl.this.tunnels.remove(plspId);
410                     //report tunnel removal to all
411                     sendToAll(tunnel, plspId, Collections.emptyList(), createSrp(0), new PathBuilder().build(),
412                         createLsp(plspId.getValue(), false, Optional.absent(), false, true));
413                 }
414             }, this.stateTimeout, TimeUnit.SECONDS);
415             tunnel.setStateTimeout(newStateTimeout);
416         }
417     }
418
419     private void startRedelegationTimer(final PCCTunnel tunnel, final PlspId plspId, final PCCSession session) {
420         final Timeout newRedelegationTimeout = this.timer.newTimeout(timeout -> {
421             //remove delegation
422             PCCTunnelManagerImpl.this.setDelegation(plspId, null);
423             //delegate to another PCE
424             int index = session.getId();
425             for (int i = 1; i < PCCTunnelManagerImpl.this.sessions.size(); i++) {
426                 index++;
427                 if (index == PCCTunnelManagerImpl.this.sessions.size()) {
428                     index = 0;
429                 }
430                 final PCCSession nextSession = PCCTunnelManagerImpl.this.sessions.get(index);
431                 if (nextSession != null) {
432                     tunnel.cancelTimeouts();
433                     final Tlvs tlvs = buildTlvs(tunnel, plspId.getValue(), Optional.absent());
434
435                     nextSession.sendReport(createPcRtpMessage(
436                         createLsp(plspId.getValue(), true, Optional.fromNullable(tlvs), true, false), NO_SRP,
437                         tunnel.getLspState()));
438                     tunnel.setDelegationHolder(nextSession.getId());
439                     break;
440                 }
441             }
442         }, this.redelegationTimeout, TimeUnit.SECONDS);
443         tunnel.setRedelegationTimeout(newRedelegationTimeout);
444     }
445
446     private void setDelegation(final PlspId plspId, final PCCSession session) {
447         final PCCTunnel tunnel = this.tunnels.get(plspId);
448         final int sessionId;
449         if (session != null) {
450             sessionId = session.getId();
451         } else {
452             sessionId = PCCTunnelBuilder.PCC_DELEGATION;
453         }
454         tunnel.setDelegationHolder(sessionId);
455     }
456
457     private static boolean hasDelegation(final PCCTunnel tunnel, final PCCSession session) {
458         final int sessionId = session.getId();
459         final int delegationHolder = tunnel.getDelegationHolder();
460         return delegationHolder == sessionId;
461     }
462
463     private static String getDestinationAddress(final List<Subobject> subobjects, final String defaultAddress) {
464         if ((subobjects != null) && !subobjects.isEmpty()) {
465             final String prefix = ((IpPrefixCase) subobjects.get(subobjects.size() - 1).getSubobjectType())
466                 .getIpPrefix().getIpPrefix().getIpv4Prefix().getValue();
467             return prefix.substring(0, prefix.indexOf('/'));
468         }
469         return defaultAddress;
470     }
471 }