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
)
261 mpls_return_enum retval
;
262 mpls_if_handle handle
;
264 void (*callback
) (mpls_timer_handle timer
, void *extra
, mpls_cfg_handle g
);
266 MPLS_ASSERT(s
&& g
&& (s
->oper_role
!= LDP_NONE
));
268 LDP_ENTER(g
->user_data
, "ldp_session_startup");
270 /* when we make it to operational, get rid of any backoff timers */
271 ldp_session_backoff_stop(g
, s
);
272 s
->state
= LDP_STATE_OPERATIONAL
;
273 s
->oper_up
= time(NULL
);
275 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
276 "ldp_session_startup: (%d) changed to OPERATIONAL\n", s
->index
);
279 * if configured to distribute addr messages walk the if table
280 * and send an addr message for each
282 if (g
->send_address_messages
) {
284 retval
= mpls_ifmgr_getfirst_address(g
->ifmgr_handle
, &handle
, &addr
);
285 while (retval
== MPLS_SUCCESS
) {
286 if (mpls_policy_address_export_check(g
->user_data
, &addr
) ==
288 ldp_addr_send(g
, s
, &addr
);
290 retval
= mpls_ifmgr_getnext_address(g
->ifmgr_handle
, &handle
, &addr
);
292 if (retval
!= MPLS_END_OF_LIST
) {
293 goto ldp_session_startup_end
;
297 /* depending on the mode, grab a pointer to the correct callback */
298 switch (s
->oper_distribution_mode
) {
299 case LDP_DISTRIBUTION_ONDEMAND
:
300 callback
= ldp_label_request_initial_callback
;
302 case LDP_DISTRIBUTION_UNSOLICITED
:
303 callback
= ldp_label_mapping_initial_callback
;
310 * create a timer which will go about "chunking" the initial
311 * set of requests or mappings
314 s
->initial_distribution_timer
= mpls_timer_create(g
->timer_handle
,
315 MPLS_UNIT_SEC
, LDP_REQUEST_CHUNK
, (void *)s
, g
, callback
);
317 if (mpls_timer_handle_verify(g
->timer_handle
,
318 s
->initial_distribution_timer
) == MPLS_BOOL_FALSE
) {
319 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
321 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
322 "ldp_session_startup: initial distrib error(%d)\n", s
->index
);
324 /* timer error, we might as well shutdown the session, it's usless */
325 s
->shutdown_notif
= LDP_NOTIF_INTERNAL_ERROR
;
326 s
->shutdown_fatal
= MPLS_BOOL_TRUE
;
327 retval
= MPLS_FAILURE
;
329 mpls_timer_start(g
->timer_handle
, s
->initial_distribution_timer
,
331 retval
= MPLS_SUCCESS
;
334 ldp_session_startup_end
:
336 LDP_EXIT(g
->user_data
, "ldp_session_startup");
341 void ldp_session_shutdown(ldp_global
* g
, ldp_session
* s
, mpls_bool complete
)
344 ldp_attr
*attr
= NULL
;
345 ldp_attr
*temp_attr
= NULL
;
350 LDP_ENTER(g
->user_data
, "ldp_session_shutdown");
353 * hold a refcount so this session doesn't disappear on us
358 s
->state
= LDP_STATE_NONE
;
359 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
360 "ldp_session_shutdown: (%d) changed to NONE\n", s
->index
);
363 * kill the timers for the session
365 if (mpls_timer_handle_verify(g
->timer_handle
, s
->keepalive_recv_timer
) ==
367 mpls_timer_stop(g
->timer_handle
, s
->keepalive_recv_timer
);
368 mpls_timer_delete(g
->timer_handle
, s
->keepalive_recv_timer
);
369 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
370 s
->keepalive_recv_timer
= (mpls_timer_handle
) 0;
372 if (mpls_timer_handle_verify(g
->timer_handle
, s
->keepalive_send_timer
) ==
374 mpls_timer_stop(g
->timer_handle
, s
->keepalive_send_timer
);
375 mpls_timer_delete(g
->timer_handle
, s
->keepalive_send_timer
);
376 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
377 s
->keepalive_send_timer
= (mpls_timer_handle
) 0;
379 if (mpls_timer_handle_verify(g
->timer_handle
,s
->initial_distribution_timer
) ==
381 mpls_timer_stop(g
->timer_handle
, s
->initial_distribution_timer
);
382 mpls_timer_delete(g
->timer_handle
, s
->initial_distribution_timer
);
383 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
384 s
->initial_distribution_timer
= (mpls_timer_handle
) 0;
388 * get rid of the socket
390 if (mpls_socket_handle_verify(g
->socket_handle
, s
->socket
) ==
392 mpls_socket_readlist_del(g
->socket_handle
, s
->socket
);
393 mpls_socket_close(g
->socket_handle
, s
->socket
);
397 * get rid of out cached keepalive
399 if (s
->keepalive
!= NULL
) {
400 ldp_mesg_delete(s
->keepalive
);
404 ldp_session_backoff_stop(g
,s
);
406 attr
= MPLS_LIST_HEAD(&g
->attr
);
407 while (attr
!= NULL
) {
408 if (attr
->session
&& attr
->session
->index
== s
->index
) {
410 MPLS_REFCNT_HOLD(temp_attr
);
412 * ldp_attr_remove_complete removed everythig associated with the attr.
413 * in and out labels, and cross connects as well
415 ldp_attr_remove_complete(g
, attr
, complete
);
419 attr
= MPLS_LIST_NEXT(&g
->attr
, attr
, _global
);
421 MPLS_REFCNT_RELEASE(temp_attr
, ldp_attr_delete
);
425 * clean up the addrs we created
427 while ((a
= (ldp_addr
*)mpls_link_list_head_data(&s
->addr_root
))) {
428 ldp_session_del_addr(g
, s
, a
);
432 * if we have an adj AND we are shuting down for a protocol reason, start a
433 * backoff timer, so we can try again in the near future
435 if ((complete
== MPLS_BOOL_TRUE
) || (s
->oper_role
!= LDP_ACTIVE
)) {
436 while ((ap
= MPLS_LIST_HEAD(&s
->adj_root
))) {
437 ldp_adj_del_session(ap
, s
);
440 if (s
->on_global
== MPLS_BOOL_TRUE
) {
441 _ldp_global_del_session(g
, s
);
444 if (s
->oper_role
== LDP_ACTIVE
) {
445 ldp_session_backoff_start(g
, s
);
450 * it is safe to release this refcnt now, if it is the last one, the
451 * session will be deleted (this will be the last one in the case of
452 * 'complete' == MPLS_BOOL_TRUE
454 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
456 LDP_EXIT(g
->user_data
, "ldp_session_shutdown");
459 mpls_return_enum
ldp_session_maintain_timer(ldp_global
* g
, ldp_session
* s
,
462 mpls_return_enum result
= MPLS_FAILURE
;
464 LDP_ENTER(g
->user_data
, "ldp_session_maintain_timer");
467 * all session keepalive maintainance comes through here (SEND and RECV)
469 if (flag
== LDP_KEEPALIVE_RECV
) {
470 mpls_timer_stop(g
->timer_handle
, s
->keepalive_recv_timer
);
471 result
= mpls_timer_start(g
->timer_handle
, s
->keepalive_recv_timer
,
474 mpls_timer_stop(g
->timer_handle
, s
->keepalive_send_timer
);
475 result
= mpls_timer_start(g
->timer_handle
, s
->keepalive_send_timer
,
476 MPLS_TIMER_REOCCURRING
);
479 LDP_EXIT(g
->user_data
, "ldp_session_maintain_timer");
484 void ldp_session_add_outlabel(ldp_session
* s
, ldp_outlabel
* o
)
488 MPLS_LIST_ADD_HEAD(&s
->outlabel_root
, o
, _session
, ldp_outlabel
);
489 _ldp_outlabel_add_session(o
, s
);
492 void ldp_session_del_outlabel(ldp_session
* s
, ldp_outlabel
* o
)
495 MPLS_LIST_REMOVE(&s
->outlabel_root
, o
, _session
);
496 _ldp_outlabel_del_session(o
);
497 MPLS_REFCNT_RELEASE(o
, ldp_outlabel_delete
);
500 mpls_return_enum
ldp_session_add_inlabel(ldp_session
* s
, ldp_inlabel
* i
)
504 if (mpls_link_list_add_tail(&s
->inlabel_root
, i
) == MPLS_SUCCESS
) {
505 if (_ldp_inlabel_add_session(i
, s
) == MPLS_SUCCESS
) {
508 mpls_link_list_remove_data(&s
->inlabel_root
, i
);
510 MPLS_REFCNT_RELEASE(i
, ldp_inlabel_delete
);
514 void ldp_session_del_inlabel(ldp_session
* s
, ldp_inlabel
* i
)
517 mpls_link_list_remove_data(&s
->inlabel_root
, i
);
518 _ldp_inlabel_del_session(i
, s
);
519 MPLS_REFCNT_RELEASE(i
, ldp_inlabel_delete
)
522 void _ldp_session_add_attr(ldp_session
* s
, ldp_attr
* a
)
526 MPLS_LIST_ADD_HEAD(&s
->attr_root
, a
, _session
, ldp_attr
);
529 void _ldp_session_del_attr(ldp_session
* s
, ldp_attr
* a
)
532 MPLS_LIST_REMOVE(&s
->attr_root
, a
, _session
);
533 MPLS_REFCNT_RELEASE(a
, ldp_attr_delete
);
536 mpls_return_enum
ldp_session_add_addr(ldp_global
*g
, ldp_session
* s
,
539 struct mpls_link_list_node
*lln
;
540 struct mpls_link_list_node
*llnp
;
546 lln
= mpls_link_list_node_create(a
);
548 if (_ldp_addr_add_session(a
, s
) == MPLS_SUCCESS
) {
549 MPLS_LINK_LIST_LOOP(&s
->addr_root
, data
, llnp
) {
550 if (data
->index
> a
->index
) {
551 mpls_link_list_add_node_before(&s
->addr_root
, llnp
, lln
);
556 mpls_link_list_add_node_tail(&s
->addr_root
, lln
);
559 mpls_link_list_node_delete(lln
);
561 MPLS_REFCNT_RELEASE2(g
, a
, ldp_addr_delete
);
565 void ldp_session_del_addr(ldp_global
*g
, ldp_session
* s
, ldp_addr
* a
) {
567 mpls_link_list_remove_data(&s
->addr_root
, a
);
568 _ldp_addr_del_session(a
, s
);
569 MPLS_REFCNT_RELEASE2(g
, a
, ldp_addr_delete
);
572 void _ldp_session_add_adj(ldp_session
* s
, ldp_adj
* a
)
575 struct in_addr lsr_address
;
580 s
->cfg_remote_in_ttl_less_domain
= a
->entity
->remote_in_ttl_less_domain
;
581 s
->cfg_distribution_mode
= a
->entity
->label_distribution_mode
;
582 s
->cfg_loop_detection_mode
= a
->entity
->loop_detection_mode
;
583 s
->cfg_label_request_count
= a
->entity
->label_request_count
;
584 s
->cfg_label_request_timer
= a
->entity
->label_request_timer
;
585 s
->cfg_label_space
= ldp_entity_label_space(a
->entity
);
586 s
->cfg_path_vector_limit
= a
->entity
->path_vector_limit
;
587 s
->cfg_hop_count_limit
= a
->entity
->hop_count_limit
;
588 s
->cfg_peer_tcp_port
= a
->entity
->remote_tcp_port
;
589 s
->cfg_keepalive
= a
->entity
->keepalive_timer
;
590 s
->cfg_max_pdu
= a
->entity
->max_pdu
;
592 lsr_address
.s_addr
= htonl(a
->remote_lsr_address
.u
.ipv4
);
593 sprintf(s
->session_name
, "%s:%d", inet_ntoa(lsr_address
),
594 a
->remote_label_space
);
595 s
->oper_role
= a
->role
;
597 ap
= MPLS_LIST_HEAD(&s
->adj_root
);
599 if (ap
->index
> a
->index
) {
600 MPLS_LIST_INSERT_BEFORE(&s
->adj_root
, ap
, a
, _session
);
603 ap
= MPLS_LIST_NEXT(&s
->adj_root
, ap
, _session
);
605 MPLS_LIST_ADD_TAIL(&s
->adj_root
, a
, _session
, ldp_adj
);
608 void _ldp_session_del_adj(ldp_session
* s
, ldp_adj
* a
)
611 MPLS_LIST_REMOVE(&s
->adj_root
, a
, _session
);
612 MPLS_REFCNT_RELEASE(a
, ldp_adj_delete
);
615 uint32_t _ldp_session_get_next_index()
617 uint32_t retval
= _ldp_session_next_index
;
619 _ldp_session_next_index
++;
620 if (retval
> _ldp_session_next_index
) {
621 _ldp_session_next_index
= 1;
626 mpls_return_enum
ldp_session_find_raddr_index(ldp_session
* s
, uint32_t index
,
629 struct mpls_link_list_node
*lln
;
632 if (s
&& index
> 0) {
633 /* because we sort our inserts by index, this lets us know
634 if we've "walked" past the end of the list */
636 if (mpls_link_list_isempty(&s
->addr_root
)) {
638 return MPLS_END_OF_LIST
;
641 if ((a
= (ldp_addr
*)mpls_link_list_tail_data(&s
->addr_root
))) {
642 if (a
->index
< index
) {
644 return MPLS_END_OF_LIST
;
648 MPLS_LINK_LIST_LOOP(&s
->addr_root
, a
, lln
) {
649 if (a
->index
== index
) {
659 mpls_return_enum
ldp_session_backoff_stop(ldp_global
* g
, ldp_session
* s
)
662 LDP_ENTER(g
->user_data
, "ldp_session_backoff_stop");
665 if (mpls_timer_handle_verify(g
->timer_handle
, s
->backoff_timer
) ==
668 mpls_timer_stop(g
->timer_handle
, s
->backoff_timer
);
669 mpls_timer_delete(g
->timer_handle
, s
->backoff_timer
);
670 s
->backoff_timer
= (mpls_timer_handle
) 0;
671 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
674 LDP_EXIT(g
->user_data
, "ldp_session_backoff_stop");
679 mpls_return_enum
ldp_session_backoff_start(ldp_global
* g
, ldp_session
* s
)
685 LDP_ENTER(g
->user_data
, "ldp_session_backoff_start");
687 valid
= mpls_timer_handle_verify(g
->timer_handle
,s
->backoff_timer
);
689 MPLS_ASSERT(valid
== MPLS_BOOL_FALSE
);
691 s
->backoff
+= g
->backoff_step
;
693 #if 0 /* if the above assert shouldn't be made this code should be executed */
695 /* this should never happen, but if so */
696 mpls_timer_stop(g
->timer_handle
, s
->backoff_timer
);
697 mpls_timer_delete(g
->timer_handle
, s
->backoff_timer
);
698 s
->backoff_timer
= (mpls_timer_handle
) 0;
699 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
702 if (!s
) { /* if we deleted session due to the above RELEASE */
703 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start-error");
709 s
->backoff_timer
= mpls_timer_create(g
->timer_handle
, MPLS_UNIT_SEC
,
710 s
->backoff
, (void *)s
, g
, ldp_session_backoff_callback
);
711 if (mpls_timer_handle_verify(g
->timer_handle
, s
->backoff_timer
) ==
714 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
715 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start-error");
719 if (mpls_timer_start(g
->timer_handle
, s
->backoff_timer
,
720 MPLS_TIMER_ONESHOT
) != MPLS_SUCCESS
) {
722 mpls_timer_delete(g
->timer_handle
, s
->backoff_timer
);
723 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
724 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start-error");
728 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start");
733 ldp_session
*ldp_session_for_nexthop(ldp_nexthop
*nh
)
737 if (nh
->type
& MPLS_NH_IP
) {
738 MPLS_ASSERT(mpls_link_list_count(&nh
->addr
->session_root
) < 2);
739 ldp_session
*s
= mpls_link_list_head_data(&nh
->addr
->session_root
);
744 if (nh
->type
& MPLS_NH_IF
) {
745 ldp_session
*s
= NULL
;
746 if (nh
->iff
&& (s
= mpls_link_list_head_data(&nh
->iff
->session_root
))) {
750 if (nh
->type
& MPLS_NH_OUTSEGMENT
) {