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 if_handle */
285 if (mpls_if_handle_verify(g
->ifmgr_handle
, addr
->if_handle
) ==
287 if (ldp_addr_send(g
, s
, &addr
->address
) != MPLS_SUCCESS
)
288 goto ldp_session_startup_end
;
290 addr
= MPLS_LIST_NEXT(&g
->addr
, addr
, _global
);
294 /* depending on the mode, grab a pointer to the correct callback */
295 switch (s
->oper_distribution_mode
) {
296 case LDP_DISTRIBUTION_ONDEMAND
:
297 callback
= ldp_label_request_initial_callback
;
299 case LDP_DISTRIBUTION_UNSOLICITED
:
300 callback
= ldp_label_mapping_initial_callback
;
307 * create a timer which will go about "chunking" the initial
308 * set of requests or mappings
311 s
->initial_distribution_timer
= mpls_timer_create(g
->timer_handle
,
312 MPLS_UNIT_SEC
, LDP_REQUEST_CHUNK
, (void *)s
, g
, callback
);
314 if (mpls_timer_handle_verify(g
->timer_handle
,
315 s
->initial_distribution_timer
) == MPLS_BOOL_FALSE
) {
316 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
318 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
319 "ldp_session_startup: initial distrib error(%d)\n", s
->index
);
321 /* timer error, we might as well shutdown the session, it's usless */
322 s
->shutdown_notif
= LDP_NOTIF_INTERNAL_ERROR
;
323 s
->shutdown_fatal
= MPLS_BOOL_TRUE
;
324 retval
= MPLS_FAILURE
;
326 mpls_timer_start(g
->timer_handle
, s
->initial_distribution_timer
,
328 retval
= MPLS_SUCCESS
;
331 ldp_session_startup_end
:
333 LDP_EXIT(g
->user_data
, "ldp_session_startup");
338 void ldp_session_shutdown(ldp_global
* g
, ldp_session
* s
, mpls_bool complete
)
341 ldp_attr
*attr
= NULL
;
342 ldp_attr
*temp_attr
= NULL
;
347 LDP_ENTER(g
->user_data
, "ldp_session_shutdown");
350 * hold a refcount so this session doesn't disappear on us
355 s
->state
= LDP_STATE_NONE
;
356 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
357 "ldp_session_shutdown: (%d) changed to NONE\n", s
->index
);
360 * kill the timers for the session
362 if (mpls_timer_handle_verify(g
->timer_handle
, s
->keepalive_recv_timer
) ==
364 mpls_timer_stop(g
->timer_handle
, s
->keepalive_recv_timer
);
365 mpls_timer_delete(g
->timer_handle
, s
->keepalive_recv_timer
);
366 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
367 s
->keepalive_recv_timer
= (mpls_timer_handle
) 0;
369 if (mpls_timer_handle_verify(g
->timer_handle
, s
->keepalive_send_timer
) ==
371 mpls_timer_stop(g
->timer_handle
, s
->keepalive_send_timer
);
372 mpls_timer_delete(g
->timer_handle
, s
->keepalive_send_timer
);
373 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
374 s
->keepalive_send_timer
= (mpls_timer_handle
) 0;
376 if (mpls_timer_handle_verify(g
->timer_handle
,s
->initial_distribution_timer
) ==
378 mpls_timer_stop(g
->timer_handle
, s
->initial_distribution_timer
);
379 mpls_timer_delete(g
->timer_handle
, s
->initial_distribution_timer
);
380 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
381 s
->initial_distribution_timer
= (mpls_timer_handle
) 0;
385 * get rid of the socket
387 if (mpls_socket_handle_verify(g
->socket_handle
, s
->socket
) ==
389 mpls_socket_readlist_del(g
->socket_handle
, s
->socket
);
390 mpls_socket_close(g
->socket_handle
, s
->socket
);
394 * get rid of out cached keepalive
396 if (s
->keepalive
!= NULL
) {
397 ldp_mesg_delete(s
->keepalive
);
401 ldp_session_backoff_stop(g
,s
);
403 attr
= MPLS_LIST_HEAD(&g
->attr
);
404 while (attr
!= NULL
) {
405 if (attr
->session
&& attr
->session
->index
== s
->index
) {
407 MPLS_REFCNT_HOLD(temp_attr
);
409 * ldp_attr_remove_complete removed everythig associated with the attr.
410 * in and out labels, and cross connects as well
412 ldp_attr_remove_complete(g
, attr
, complete
);
416 attr
= MPLS_LIST_NEXT(&g
->attr
, attr
, _global
);
418 MPLS_REFCNT_RELEASE(temp_attr
, ldp_attr_delete
);
422 * clean up the addrs we created
424 while ((a
= (ldp_addr
*)mpls_link_list_head_data(&s
->addr_root
))) {
425 ldp_session_del_addr(g
, s
, a
);
429 * if we have an adj AND we are shuting down for a protocol reason, start a
430 * backoff timer, so we can try again in the near future
432 if ((complete
== MPLS_BOOL_TRUE
) || (s
->oper_role
!= LDP_ACTIVE
)) {
433 while ((ap
= MPLS_LIST_HEAD(&s
->adj_root
))) {
434 ldp_adj_del_session(ap
, s
);
437 if (s
->on_global
== MPLS_BOOL_TRUE
) {
438 _ldp_global_del_session(g
, s
);
441 if (s
->oper_role
== LDP_ACTIVE
) {
442 ldp_session_backoff_start(g
, s
);
447 * it is safe to release this refcnt now, if it is the last one, the
448 * session will be deleted (this will be the last one in the case of
449 * 'complete' == MPLS_BOOL_TRUE
451 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
453 LDP_EXIT(g
->user_data
, "ldp_session_shutdown");
456 mpls_return_enum
ldp_session_maintain_timer(ldp_global
* g
, ldp_session
* s
,
459 mpls_return_enum result
= MPLS_FAILURE
;
461 LDP_ENTER(g
->user_data
, "ldp_session_maintain_timer");
464 * all session keepalive maintainance comes through here (SEND and RECV)
466 if (flag
== LDP_KEEPALIVE_RECV
) {
467 mpls_timer_stop(g
->timer_handle
, s
->keepalive_recv_timer
);
468 result
= mpls_timer_start(g
->timer_handle
, s
->keepalive_recv_timer
,
471 mpls_timer_stop(g
->timer_handle
, s
->keepalive_send_timer
);
472 result
= mpls_timer_start(g
->timer_handle
, s
->keepalive_send_timer
,
473 MPLS_TIMER_REOCCURRING
);
476 LDP_EXIT(g
->user_data
, "ldp_session_maintain_timer");
481 void ldp_session_add_outlabel(ldp_session
* s
, ldp_outlabel
* o
)
485 MPLS_LIST_ADD_HEAD(&s
->outlabel_root
, o
, _session
, ldp_outlabel
);
486 _ldp_outlabel_add_session(o
, s
);
489 void ldp_session_del_outlabel(ldp_session
* s
, ldp_outlabel
* o
)
492 MPLS_LIST_REMOVE(&s
->outlabel_root
, o
, _session
);
493 _ldp_outlabel_del_session(o
);
494 MPLS_REFCNT_RELEASE(o
, ldp_outlabel_delete
);
497 mpls_return_enum
ldp_session_add_inlabel(ldp_session
* s
, ldp_inlabel
* i
)
501 if (mpls_link_list_add_tail(&s
->inlabel_root
, i
) == MPLS_SUCCESS
) {
502 if (_ldp_inlabel_add_session(i
, s
) == MPLS_SUCCESS
) {
505 mpls_link_list_remove_data(&s
->inlabel_root
, i
);
507 MPLS_REFCNT_RELEASE(i
, ldp_inlabel_delete
);
511 void ldp_session_del_inlabel(ldp_session
* s
, ldp_inlabel
* i
)
514 mpls_link_list_remove_data(&s
->inlabel_root
, i
);
515 _ldp_inlabel_del_session(i
, s
);
516 MPLS_REFCNT_RELEASE(i
, ldp_inlabel_delete
)
519 void _ldp_session_add_attr(ldp_session
* s
, ldp_attr
* a
)
523 MPLS_LIST_ADD_HEAD(&s
->attr_root
, a
, _session
, ldp_attr
);
526 void _ldp_session_del_attr(ldp_session
* s
, ldp_attr
* a
)
529 MPLS_LIST_REMOVE(&s
->attr_root
, a
, _session
);
530 MPLS_REFCNT_RELEASE(a
, ldp_attr_delete
);
533 mpls_return_enum
ldp_session_add_addr(ldp_global
*g
, ldp_session
* s
,
536 struct mpls_link_list_node
*lln
;
537 struct mpls_link_list_node
*llnp
;
543 lln
= mpls_link_list_node_create(a
);
545 if (_ldp_addr_add_session(a
, s
) == MPLS_SUCCESS
) {
546 MPLS_LINK_LIST_LOOP(&s
->addr_root
, data
, llnp
) {
547 if (data
->index
> a
->index
) {
548 mpls_link_list_add_node_before(&s
->addr_root
, llnp
, lln
);
553 mpls_link_list_add_node_tail(&s
->addr_root
, lln
);
556 mpls_link_list_node_delete(lln
);
558 MPLS_REFCNT_RELEASE2(g
, a
, ldp_addr_delete
);
562 void ldp_session_del_addr(ldp_global
*g
, ldp_session
* s
, ldp_addr
* a
) {
564 mpls_link_list_remove_data(&s
->addr_root
, a
);
565 _ldp_addr_del_session(a
, s
);
566 MPLS_REFCNT_RELEASE2(g
, a
, ldp_addr_delete
);
569 void _ldp_session_add_adj(ldp_session
* s
, ldp_adj
* a
)
572 struct in_addr lsr_address
;
577 s
->cfg_remote_in_ttl_less_domain
= a
->entity
->remote_in_ttl_less_domain
;
578 s
->cfg_distribution_mode
= a
->entity
->label_distribution_mode
;
579 s
->cfg_loop_detection_mode
= a
->entity
->loop_detection_mode
;
580 s
->cfg_label_request_count
= a
->entity
->label_request_count
;
581 s
->cfg_label_request_timer
= a
->entity
->label_request_timer
;
582 s
->cfg_label_space
= ldp_entity_label_space(a
->entity
);
583 s
->cfg_path_vector_limit
= a
->entity
->path_vector_limit
;
584 s
->cfg_hop_count_limit
= a
->entity
->hop_count_limit
;
585 s
->cfg_peer_tcp_port
= a
->entity
->remote_tcp_port
;
586 s
->cfg_keepalive
= a
->entity
->keepalive_timer
;
587 s
->cfg_max_pdu
= a
->entity
->max_pdu
;
589 lsr_address
.s_addr
= htonl(a
->remote_lsr_address
.u
.ipv4
);
590 sprintf(s
->session_name
, "%s:%d", inet_ntoa(lsr_address
),
591 a
->remote_label_space
);
592 s
->oper_role
= a
->role
;
594 ap
= MPLS_LIST_HEAD(&s
->adj_root
);
596 if (ap
->index
> a
->index
) {
597 MPLS_LIST_INSERT_BEFORE(&s
->adj_root
, ap
, a
, _session
);
600 ap
= MPLS_LIST_NEXT(&s
->adj_root
, ap
, _session
);
602 MPLS_LIST_ADD_TAIL(&s
->adj_root
, a
, _session
, ldp_adj
);
605 void _ldp_session_del_adj(ldp_session
* s
, ldp_adj
* a
)
608 MPLS_LIST_REMOVE(&s
->adj_root
, a
, _session
);
609 MPLS_REFCNT_RELEASE(a
, ldp_adj_delete
);
612 uint32_t _ldp_session_get_next_index()
614 uint32_t retval
= _ldp_session_next_index
;
616 _ldp_session_next_index
++;
617 if (retval
> _ldp_session_next_index
) {
618 _ldp_session_next_index
= 1;
623 mpls_return_enum
ldp_session_find_raddr_index(ldp_session
* s
, uint32_t index
,
626 struct mpls_link_list_node
*lln
;
629 if (s
&& index
> 0) {
630 /* because we sort our inserts by index, this lets us know
631 if we've "walked" past the end of the list */
633 if (mpls_link_list_isempty(&s
->addr_root
)) {
635 return MPLS_END_OF_LIST
;
638 if ((a
= (ldp_addr
*)mpls_link_list_tail_data(&s
->addr_root
))) {
639 if (a
->index
< index
) {
641 return MPLS_END_OF_LIST
;
645 MPLS_LINK_LIST_LOOP(&s
->addr_root
, a
, lln
) {
646 if (a
->index
== index
) {
656 mpls_return_enum
ldp_session_backoff_stop(ldp_global
* g
, ldp_session
* s
)
659 LDP_ENTER(g
->user_data
, "ldp_session_backoff_stop");
662 if (mpls_timer_handle_verify(g
->timer_handle
, s
->backoff_timer
) ==
665 mpls_timer_stop(g
->timer_handle
, s
->backoff_timer
);
666 mpls_timer_delete(g
->timer_handle
, s
->backoff_timer
);
667 s
->backoff_timer
= (mpls_timer_handle
) 0;
668 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
671 LDP_EXIT(g
->user_data
, "ldp_session_backoff_stop");
676 mpls_return_enum
ldp_session_backoff_start(ldp_global
* g
, ldp_session
* s
)
682 LDP_ENTER(g
->user_data
, "ldp_session_backoff_start");
684 valid
= mpls_timer_handle_verify(g
->timer_handle
,s
->backoff_timer
);
686 MPLS_ASSERT(valid
== MPLS_BOOL_FALSE
);
688 s
->backoff
+= g
->backoff_step
;
690 #if 0 /* if the above assert shouldn't be made this code should be executed */
692 /* this should never happen, but if so */
693 mpls_timer_stop(g
->timer_handle
, s
->backoff_timer
);
694 mpls_timer_delete(g
->timer_handle
, s
->backoff_timer
);
695 s
->backoff_timer
= (mpls_timer_handle
) 0;
696 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
699 if (!s
) { /* if we deleted session due to the above RELEASE */
700 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start-error");
706 s
->backoff_timer
= mpls_timer_create(g
->timer_handle
, MPLS_UNIT_SEC
,
707 s
->backoff
, (void *)s
, g
, ldp_session_backoff_callback
);
708 if (mpls_timer_handle_verify(g
->timer_handle
, s
->backoff_timer
) ==
711 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
712 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start-error");
716 if (mpls_timer_start(g
->timer_handle
, s
->backoff_timer
,
717 MPLS_TIMER_ONESHOT
) != MPLS_SUCCESS
) {
719 mpls_timer_delete(g
->timer_handle
, s
->backoff_timer
);
720 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
721 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start-error");
725 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start");
730 ldp_session
*ldp_session_for_nexthop(ldp_nexthop
*nh
)
734 if (nh
->info
.type
& MPLS_NH_IP
) {
735 MPLS_ASSERT(mpls_link_list_count(&nh
->addr
->session_root
) < 2);
736 ldp_session
*s
= mpls_link_list_head_data(&nh
->addr
->session_root
);
741 if (nh
->info
.type
& MPLS_NH_IF
) {
742 ldp_session
*s
= NULL
;
743 if (nh
->iff
&& (s
= mpls_link_list_head_data(&nh
->iff
->session_root
))) {
747 if (nh
->info
.type
& MPLS_NH_OUTSEGMENT
) {