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