3 * Copyright (C) James R. Leu 2000
6 * This software is covered under the LGPL, for more
7 * info check out http://www.gnu.org/copyleft/lgpl.html
11 #include "ldp_struct.h"
12 #include "ldp_outlabel.h"
13 #include "ldp_session.h"
14 #include "ldp_entity.h"
15 #include "ldp_inlabel.h"
16 #include "ldp_outlabel.h"
22 #include "ldp_inet_addr.h"
23 #include "ldp_global.h"
24 #include "ldp_state_machine.h"
25 #include "ldp_label_rel_with.h"
26 #include "ldp_label_request.h"
27 #include "ldp_label_mapping.h"
29 #include "mpls_refcnt.h"
30 #include "mpls_assert.h"
31 #include "mpls_mm_impl.h"
32 #include "mpls_timer_impl.h"
33 #include "mpls_socket_impl.h"
34 #include "mpls_trace_impl.h"
35 #include "mpls_ifmgr_impl.h"
36 #include "mpls_policy_impl.h"
37 #include "mpls_lock_impl.h"
39 static uint32_t _ldp_session_next_index
= 1;
41 mpls_return_enum
ldp_session_attempt_setup(ldp_global
*g
, ldp_session
*s
);
42 mpls_return_enum
ldp_session_backoff_stop(ldp_global
* g
, ldp_session
* s
);
44 static void ldp_session_backoff_callback(mpls_timer_handle timer
, void *extra
,
45 mpls_cfg_handle handle
)
47 ldp_session
*s
= (ldp_session
*)extra
;
48 ldp_global
*g
= (ldp_global
*)handle
;
50 LDP_ENTER(g
->user_data
, "ldp_session_backoff");
52 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_TIMER
,
53 "Session Backoff Timer fired: session(%s)\n", s
->session_name
);
55 mpls_lock_get(g
->global_lock
);
59 if (s
->oper_role
== LDP_ACTIVE
) {
60 if (ldp_session_attempt_setup(g
, s
) != MPLS_SUCCESS
) {
61 s
->backoff
+= g
->backoff_step
;
62 s
->backoff_timer
= timer
;
63 mpls_timer_start(g
->timer_handle
, timer
, MPLS_TIMER_ONESHOT
);
65 LDP_EXIT(g
->user_data
, "ldp_session_backoff-error");
67 goto ldp_session_backoff_end
;
69 } else if (s
->oper_role
== LDP_PASSIVE
) {
70 /* this is a passive session that never received an init, kill it
71 * session current on the global list and the timer holds a refcnt.
72 * shutdown takes this session off of the global list, so when the
73 * timer refcnt is released the session will be deleted */
74 ldp_session_shutdown(g
, s
, MPLS_BOOL_TRUE
);
79 mpls_timer_stop(g
->timer_handle
, timer
);
80 mpls_timer_delete(g
->timer_handle
, timer
);
81 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
83 ldp_session_backoff_end
:
85 mpls_lock_release(g
->global_lock
);
87 LDP_EXIT(g
->user_data
, "ldp_session_backoff");
90 ldp_session
*ldp_session_create()
92 ldp_session
*s
= (ldp_session
*) mpls_malloc(sizeof(ldp_session
));
95 memset(s
, 0, sizeof(ldp_session
));
96 MPLS_REFCNT_INIT(s
, 0);
97 MPLS_LIST_ELEM_INIT(s
, _global
);
98 MPLS_LIST_INIT(&s
->outlabel_root
, ldp_outlabel
);
99 MPLS_LIST_INIT(&s
->attr_root
, ldp_attr
);
100 MPLS_LIST_INIT(&s
->adj_root
, ldp_adj
);
101 mpls_link_list_init(&s
->inlabel_root
);
102 mpls_link_list_init(&s
->addr_root
);
104 s
->on_global
= MPLS_BOOL_FALSE
;
105 s
->tx_buffer
= ldp_buf_create(MPLS_PDUMAXLEN
);
106 s
->tx_message
= ldp_mesg_create();
107 s
->index
= _ldp_session_get_next_index();
108 s
->oper_role
= LDP_NONE
;
113 mpls_return_enum
ldp_session_attempt_setup(ldp_global
*g
, ldp_session
*s
) {
114 mpls_socket_handle socket
= mpls_socket_create_tcp(g
->socket_handle
);
115 mpls_return_enum retval
;
117 LDP_ENTER(g
->user_data
, "ldp_session_attempt_setup");
119 if (mpls_socket_handle_verify(g
->socket_handle
, socket
) == MPLS_BOOL_FALSE
) {
122 if (mpls_socket_options(g
->socket_handle
, socket
, MPLS_SOCKOP_NONBLOCK
) ==
124 goto ldp_session_attempt_setup_error
;
127 retval
= mpls_socket_tcp_connect(g
->socket_handle
, socket
, &s
->remote_dest
);
130 case MPLS_NON_BLOCKING
:
132 LDP_TRACE_OUT(g
->user_data
,
133 "ldp_session_attempt_setup: MPLS_NON_BLOCKING\n");
134 mpls_socket_writelist_add(g
->socket_handle
, socket
, (void *)s
,
135 MPLS_SOCKET_TCP_CONNECT
);
140 LDP_TRACE_OUT(g
->user_data
,
141 "ldp_session_attempt_setup: MPLS_SUCCESS\n");
142 if (ldp_state_machine(g
, s
, NULL
, NULL
, LDP_EVENT_CONNECT
, NULL
,
143 NULL
) == MPLS_FAILURE
) {
144 goto ldp_session_attempt_setup_error
;
150 LDP_TRACE_OUT(g
->user_data
,
151 "ldp_session_attempt_setup: MPLS_FAILURE\n");
152 goto ldp_session_attempt_setup_error
;
158 LDP_EXIT(g
->user_data
, "ldp_session_attempt_setup");
161 ldp_session_attempt_setup_error
:
163 mpls_socket_close(g
->socket_handle
, socket
);
164 LDP_EXIT(g
->user_data
, "ldp_session_attempt_setup");
168 mpls_return_enum
ldp_session_create_active(ldp_global
* g
, ldp_adj
* a
)
170 mpls_return_enum retval
= MPLS_FAILURE
;
171 mpls_inet_addr
*addr
= NULL
;
172 ldp_session
*s
= NULL
;
175 MPLS_ASSERT(g
&& a
&& (!a
->session
));
177 LDP_ENTER(g
->user_data
, "ldp_session_create_active");
179 ap
= MPLS_LIST_HEAD(&g
->adj
);
181 if ((!mpls_inet_addr_compare(&ap
->remote_lsr_address
,
182 &a
->remote_lsr_address
)) &&
183 ap
->remote_label_space
== a
->remote_label_space
&&
184 a
->index
!= ap
->index
&& ap
->session
) {
185 ldp_adj_add_session(a
, ap
->session
);
186 retval
= MPLS_SUCCESS
;
187 goto ldp_session_create_active
;
189 ap
= MPLS_LIST_NEXT(&g
->adj
, ap
, _global
);
192 if ((s
= ldp_session_create())) {
193 if (a
->remote_transport_address
.type
!= MPLS_FAMILY_NONE
) {
194 addr
= &a
->remote_transport_address
;
196 addr
= &a
->remote_source_address
;
199 _ldp_global_add_session(g
, s
);
200 ldp_adj_add_session(a
, s
);
201 s
->state
= LDP_STATE_NON_EXIST
;
203 memcpy(&s
->remote_dest
.addr
, addr
, sizeof(mpls_inet_addr
));
204 s
->remote_dest
.port
= s
->cfg_peer_tcp_port
;
206 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
207 "ldp_session_create_active: (%d) changed to NON_EXIST\n", s
->index
);
209 if (ldp_session_attempt_setup(g
, s
) != MPLS_SUCCESS
) {
210 /* go into backoff */
211 ldp_session_backoff_start(g
, s
);
213 retval
= MPLS_SUCCESS
;
216 ldp_session_create_active
:
218 LDP_EXIT(g
->user_data
, "ldp_session_create_active");
222 ldp_session
*ldp_session_create_passive(ldp_global
* g
,
223 mpls_socket_handle socket
, mpls_dest
* from
)
225 ldp_session
*s
= NULL
;
229 LDP_ENTER(g
->user_data
, "ldp_session_create_passive");
231 if ((s
= ldp_session_create())) {
233 s
->state
= LDP_STATE_NON_EXIST
;
235 if (mpls_socket_options(g
->socket_handle
, socket
, MPLS_SOCKOP_NONBLOCK
) ==
237 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
238 "ldp_session_create_passive: (%d) changed to NON_EXIST\n", s
->index
);
239 _ldp_global_add_session(g
, s
);
241 ldp_session_delete(s
);
246 LDP_EXIT(g
->user_data
, "ldp_session_create_passive (%p)", s
);
251 void ldp_session_delete(ldp_session
* s
)
253 fprintf(stderr
,"session delete\n");
254 MPLS_REFCNT_ASSERT(s
, 0);
258 mpls_return_enum
ldp_session_startup(ldp_global
* g
, ldp_session
* s
)
260 mpls_return_enum retval
= MPLS_FAILURE
;
263 void (*callback
) (mpls_timer_handle timer
, void *extra
, mpls_cfg_handle g
);
265 MPLS_ASSERT(s
&& g
&& (s
->oper_role
!= LDP_NONE
));
267 LDP_ENTER(g
->user_data
, "ldp_session_startup");
269 /* when we make it to operational, get rid of any backoff timers */
270 ldp_session_backoff_stop(g
, s
);
271 s
->state
= LDP_STATE_OPERATIONAL
;
272 s
->oper_up
= time(NULL
);
274 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
275 "ldp_session_startup: (%d) changed to OPERATIONAL\n", s
->index
);
278 * if configured to distribute addr messages walk the if table
279 * and send an addr message for each
281 if (g
->send_address_messages
) {
282 addr
= MPLS_LIST_HEAD(&g
->addr
);
284 /* only locally attached addrs will have a valid iff */
286 if (ldp_addr_send(g
, s
, &addr
->address
) != MPLS_SUCCESS
)
287 goto ldp_session_startup_end
;
289 addr
= MPLS_LIST_NEXT(&g
->addr
, addr
, _global
);
293 /* depending on the mode, grab a pointer to the correct callback */
294 switch (s
->oper_distribution_mode
) {
295 case LDP_DISTRIBUTION_ONDEMAND
:
296 callback
= ldp_label_request_initial_callback
;
298 case LDP_DISTRIBUTION_UNSOLICITED
:
299 callback
= ldp_label_mapping_initial_callback
;
306 * create a timer which will go about "chunking" the initial
307 * set of requests or mappings
310 s
->initial_distribution_timer
= mpls_timer_create(g
->timer_handle
,
311 MPLS_UNIT_SEC
, LDP_REQUEST_CHUNK
, (void *)s
, g
, callback
);
313 if (mpls_timer_handle_verify(g
->timer_handle
,
314 s
->initial_distribution_timer
) == MPLS_BOOL_FALSE
) {
315 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
317 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
318 "ldp_session_startup: initial distrib error(%d)\n", s
->index
);
320 /* timer error, we might as well shutdown the session, it's usless */
321 s
->shutdown_notif
= LDP_NOTIF_INTERNAL_ERROR
;
322 s
->shutdown_fatal
= MPLS_BOOL_TRUE
;
323 retval
= MPLS_FAILURE
;
325 mpls_timer_start(g
->timer_handle
, s
->initial_distribution_timer
,
327 retval
= MPLS_SUCCESS
;
330 ldp_session_startup_end
:
332 LDP_EXIT(g
->user_data
, "ldp_session_startup");
337 void ldp_session_shutdown(ldp_global
* g
, ldp_session
* s
, mpls_bool complete
)
340 ldp_attr
*attr
= NULL
;
341 ldp_attr
*temp_attr
= NULL
;
346 LDP_ENTER(g
->user_data
, "ldp_session_shutdown");
349 * hold a refcount so this session doesn't disappear on us
354 s
->state
= LDP_STATE_NONE
;
355 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
356 "ldp_session_shutdown: (%d) changed to NONE\n", s
->index
);
359 * kill the timers for the session
361 if (mpls_timer_handle_verify(g
->timer_handle
, s
->keepalive_recv_timer
) ==
363 mpls_timer_stop(g
->timer_handle
, s
->keepalive_recv_timer
);
364 mpls_timer_delete(g
->timer_handle
, s
->keepalive_recv_timer
);
365 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
366 s
->keepalive_recv_timer
= (mpls_timer_handle
) 0;
368 if (mpls_timer_handle_verify(g
->timer_handle
, s
->keepalive_send_timer
) ==
370 mpls_timer_stop(g
->timer_handle
, s
->keepalive_send_timer
);
371 mpls_timer_delete(g
->timer_handle
, s
->keepalive_send_timer
);
372 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
373 s
->keepalive_send_timer
= (mpls_timer_handle
) 0;
375 if (mpls_timer_handle_verify(g
->timer_handle
,s
->initial_distribution_timer
) ==
377 mpls_timer_stop(g
->timer_handle
, s
->initial_distribution_timer
);
378 mpls_timer_delete(g
->timer_handle
, s
->initial_distribution_timer
);
379 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
380 s
->initial_distribution_timer
= (mpls_timer_handle
) 0;
384 * get rid of the socket
386 if (mpls_socket_handle_verify(g
->socket_handle
, s
->socket
) ==
388 mpls_socket_readlist_del(g
->socket_handle
, s
->socket
);
389 mpls_socket_close(g
->socket_handle
, s
->socket
);
393 * get rid of out cached keepalive
395 if (s
->keepalive
!= NULL
) {
396 ldp_mesg_delete(s
->keepalive
);
400 ldp_session_backoff_stop(g
,s
);
402 attr
= MPLS_LIST_HEAD(&g
->attr
);
403 while (attr
!= NULL
) {
404 if (attr
->session
&& attr
->session
->index
== s
->index
) {
406 MPLS_REFCNT_HOLD(temp_attr
);
408 * ldp_attr_remove_complete removed everythig associated with the attr.
409 * in and out labels, and cross connects as well
411 ldp_attr_remove_complete(g
, attr
, complete
);
415 attr
= MPLS_LIST_NEXT(&g
->attr
, attr
, _global
);
417 MPLS_REFCNT_RELEASE(temp_attr
, ldp_attr_delete
);
421 * clean up the addrs we created
423 while ((a
= (ldp_addr
*)mpls_link_list_head_data(&s
->addr_root
))) {
424 ldp_session_del_addr(g
, s
, a
);
428 * if we have an adj AND we are shuting down for a protocol reason, start a
429 * backoff timer, so we can try again in the near future
431 if ((complete
== MPLS_BOOL_TRUE
) || (s
->oper_role
!= LDP_ACTIVE
)) {
432 while ((ap
= MPLS_LIST_HEAD(&s
->adj_root
))) {
433 ldp_adj_del_session(ap
, s
);
436 if (s
->on_global
== MPLS_BOOL_TRUE
) {
437 _ldp_global_del_session(g
, s
);
440 if (s
->oper_role
== LDP_ACTIVE
) {
441 ldp_session_backoff_start(g
, s
);
446 * it is safe to release this refcnt now, if it is the last one, the
447 * session will be deleted (this will be the last one in the case of
448 * 'complete' == MPLS_BOOL_TRUE
450 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
452 LDP_EXIT(g
->user_data
, "ldp_session_shutdown");
455 mpls_return_enum
ldp_session_maintain_timer(ldp_global
* g
, ldp_session
* s
,
458 mpls_return_enum result
= MPLS_FAILURE
;
460 LDP_ENTER(g
->user_data
, "ldp_session_maintain_timer");
463 * all session keepalive maintainance comes through here (SEND and RECV)
465 if (flag
== LDP_KEEPALIVE_RECV
) {
466 mpls_timer_stop(g
->timer_handle
, s
->keepalive_recv_timer
);
467 result
= mpls_timer_start(g
->timer_handle
, s
->keepalive_recv_timer
,
470 mpls_timer_stop(g
->timer_handle
, s
->keepalive_send_timer
);
471 result
= mpls_timer_start(g
->timer_handle
, s
->keepalive_send_timer
,
472 MPLS_TIMER_REOCCURRING
);
475 LDP_EXIT(g
->user_data
, "ldp_session_maintain_timer");
480 void ldp_session_add_outlabel(ldp_session
* s
, ldp_outlabel
* o
)
484 MPLS_LIST_ADD_HEAD(&s
->outlabel_root
, o
, _session
, ldp_outlabel
);
485 _ldp_outlabel_add_session(o
, s
);
488 void ldp_session_del_outlabel(ldp_session
* s
, ldp_outlabel
* o
)
491 MPLS_LIST_REMOVE(&s
->outlabel_root
, o
, _session
);
492 _ldp_outlabel_del_session(o
);
493 MPLS_REFCNT_RELEASE(o
, ldp_outlabel_delete
);
496 mpls_return_enum
ldp_session_add_inlabel(ldp_session
* s
, ldp_inlabel
* i
)
500 if (mpls_link_list_add_tail(&s
->inlabel_root
, i
) == MPLS_SUCCESS
) {
501 if (_ldp_inlabel_add_session(i
, s
) == MPLS_SUCCESS
) {
504 mpls_link_list_remove_data(&s
->inlabel_root
, i
);
506 MPLS_REFCNT_RELEASE(i
, ldp_inlabel_delete
);
510 void ldp_session_del_inlabel(ldp_session
* s
, ldp_inlabel
* i
)
513 mpls_link_list_remove_data(&s
->inlabel_root
, i
);
514 _ldp_inlabel_del_session(i
, s
);
515 MPLS_REFCNT_RELEASE(i
, ldp_inlabel_delete
)
518 void _ldp_session_add_attr(ldp_session
* s
, ldp_attr
* a
)
522 MPLS_LIST_ADD_HEAD(&s
->attr_root
, a
, _session
, ldp_attr
);
525 void _ldp_session_del_attr(ldp_session
* s
, ldp_attr
* a
)
528 MPLS_LIST_REMOVE(&s
->attr_root
, a
, _session
);
529 MPLS_REFCNT_RELEASE(a
, ldp_attr_delete
);
532 mpls_return_enum
ldp_session_add_addr(ldp_global
*g
, ldp_session
* s
,
535 struct mpls_link_list_node
*lln
;
536 struct mpls_link_list_node
*llnp
;
542 lln
= mpls_link_list_node_create(a
);
544 if (_ldp_addr_add_session(a
, s
) == MPLS_SUCCESS
) {
545 MPLS_LINK_LIST_LOOP(&s
->addr_root
, data
, llnp
) {
546 if (data
->index
> a
->index
) {
547 mpls_link_list_add_node_before(&s
->addr_root
, llnp
, lln
);
552 mpls_link_list_add_node_tail(&s
->addr_root
, lln
);
555 mpls_link_list_node_delete(lln
);
557 MPLS_REFCNT_RELEASE2(g
, a
, ldp_addr_delete
);
561 void ldp_session_del_addr(ldp_global
*g
, ldp_session
* s
, ldp_addr
* a
) {
563 mpls_link_list_remove_data(&s
->addr_root
, a
);
564 _ldp_addr_del_session(a
, s
);
565 MPLS_REFCNT_RELEASE2(g
, a
, ldp_addr_delete
);
568 void _ldp_session_add_adj(ldp_session
* s
, ldp_adj
* a
)
571 struct in_addr lsr_address
;
576 s
->cfg_remote_in_ttl_less_domain
= a
->entity
->remote_in_ttl_less_domain
;
577 s
->cfg_distribution_mode
= a
->entity
->label_distribution_mode
;
578 s
->cfg_loop_detection_mode
= a
->entity
->loop_detection_mode
;
579 s
->cfg_label_request_count
= a
->entity
->label_request_count
;
580 s
->cfg_label_request_timer
= a
->entity
->label_request_timer
;
581 s
->cfg_label_space
= ldp_entity_label_space(a
->entity
);
582 s
->cfg_path_vector_limit
= a
->entity
->path_vector_limit
;
583 s
->cfg_hop_count_limit
= a
->entity
->hop_count_limit
;
584 s
->cfg_peer_tcp_port
= a
->entity
->remote_tcp_port
;
585 s
->cfg_keepalive
= a
->entity
->keepalive_timer
;
586 s
->cfg_max_pdu
= a
->entity
->max_pdu
;
588 lsr_address
.s_addr
= htonl(a
->remote_lsr_address
.u
.ipv4
);
589 sprintf(s
->session_name
, "%s:%d", inet_ntoa(lsr_address
),
590 a
->remote_label_space
);
591 s
->oper_role
= a
->role
;
593 ap
= MPLS_LIST_HEAD(&s
->adj_root
);
595 if (ap
->index
> a
->index
) {
596 MPLS_LIST_INSERT_BEFORE(&s
->adj_root
, ap
, a
, _session
);
599 ap
= MPLS_LIST_NEXT(&s
->adj_root
, ap
, _session
);
601 MPLS_LIST_ADD_TAIL(&s
->adj_root
, a
, _session
, ldp_adj
);
604 void _ldp_session_del_adj(ldp_session
* s
, ldp_adj
* a
)
607 MPLS_LIST_REMOVE(&s
->adj_root
, a
, _session
);
608 MPLS_REFCNT_RELEASE(a
, ldp_adj_delete
);
611 uint32_t _ldp_session_get_next_index()
613 uint32_t retval
= _ldp_session_next_index
;
615 _ldp_session_next_index
++;
616 if (retval
> _ldp_session_next_index
) {
617 _ldp_session_next_index
= 1;
622 mpls_return_enum
ldp_session_find_raddr_index(ldp_session
* s
, uint32_t index
,
625 struct mpls_link_list_node
*lln
;
628 if (s
&& index
> 0) {
629 /* because we sort our inserts by index, this lets us know
630 if we've "walked" past the end of the list */
632 if (mpls_link_list_isempty(&s
->addr_root
)) {
634 return MPLS_END_OF_LIST
;
637 if ((a
= (ldp_addr
*)mpls_link_list_tail_data(&s
->addr_root
))) {
638 if (a
->index
< index
) {
640 return MPLS_END_OF_LIST
;
644 MPLS_LINK_LIST_LOOP(&s
->addr_root
, a
, lln
) {
645 if (a
->index
== index
) {
655 mpls_return_enum
ldp_session_backoff_stop(ldp_global
* g
, ldp_session
* s
)
658 LDP_ENTER(g
->user_data
, "ldp_session_backoff_stop");
661 if (mpls_timer_handle_verify(g
->timer_handle
, s
->backoff_timer
) ==
664 mpls_timer_stop(g
->timer_handle
, s
->backoff_timer
);
665 mpls_timer_delete(g
->timer_handle
, s
->backoff_timer
);
666 s
->backoff_timer
= (mpls_timer_handle
) 0;
667 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
670 LDP_EXIT(g
->user_data
, "ldp_session_backoff_stop");
675 mpls_return_enum
ldp_session_backoff_start(ldp_global
* g
, ldp_session
* s
)
681 LDP_ENTER(g
->user_data
, "ldp_session_backoff_start");
683 valid
= mpls_timer_handle_verify(g
->timer_handle
,s
->backoff_timer
);
685 MPLS_ASSERT(valid
== MPLS_BOOL_FALSE
);
687 s
->backoff
+= g
->backoff_step
;
689 #if 0 /* if the above assert shouldn't be made this code should be executed */
691 /* this should never happen, but if so */
692 mpls_timer_stop(g
->timer_handle
, s
->backoff_timer
);
693 mpls_timer_delete(g
->timer_handle
, s
->backoff_timer
);
694 s
->backoff_timer
= (mpls_timer_handle
) 0;
695 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
698 if (!s
) { /* if we deleted session due to the above RELEASE */
699 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start-error");
705 s
->backoff_timer
= mpls_timer_create(g
->timer_handle
, MPLS_UNIT_SEC
,
706 s
->backoff
, (void *)s
, g
, ldp_session_backoff_callback
);
707 if (mpls_timer_handle_verify(g
->timer_handle
, s
->backoff_timer
) ==
710 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
711 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start-error");
715 if (mpls_timer_start(g
->timer_handle
, s
->backoff_timer
,
716 MPLS_TIMER_ONESHOT
) != MPLS_SUCCESS
) {
718 mpls_timer_delete(g
->timer_handle
, s
->backoff_timer
);
719 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
720 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start-error");
724 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start");
729 ldp_session
*ldp_session_for_nexthop(ldp_nexthop
*nh
)
733 if (nh
->info
.type
& MPLS_NH_IP
) {
734 MPLS_ASSERT(mpls_link_list_count(&nh
->addr
->session_root
) < 2);
735 ldp_session
*s
= mpls_link_list_head_data(&nh
->addr
->session_root
);
740 if (nh
->info
.type
& MPLS_NH_IF
) {
741 ldp_session
*s
= NULL
;
742 if (nh
->iff
&& (s
= mpls_link_list_head_data(&nh
->iff
->session_root
))) {
746 if (nh
->info
.type
& MPLS_NH_OUTSEGMENT
) {