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(
93 MTYPE_LDP_SESSION
, sizeof(ldp_session
));
96 memset(s
, 0, sizeof(ldp_session
));
97 MPLS_REFCNT_INIT(s
, 0);
98 MPLS_LIST_ELEM_INIT(s
, _global
);
99 MPLS_LIST_INIT(&s
->outlabel_root
, ldp_outlabel
);
100 MPLS_LIST_INIT(&s
->attr_root
, ldp_attr
);
101 MPLS_LIST_INIT(&s
->adj_root
, ldp_adj
);
102 mpls_link_list_init(&s
->inlabel_root
);
103 mpls_link_list_init(&s
->addr_root
);
105 s
->on_global
= MPLS_BOOL_FALSE
;
106 s
->tx_buffer
= ldp_buf_create(MPLS_PDUMAXLEN
);
107 s
->tx_message
= ldp_mesg_create();
108 s
->index
= _ldp_session_get_next_index();
109 s
->oper_role
= LDP_NONE
;
114 mpls_return_enum
ldp_session_attempt_setup(ldp_global
*g
, ldp_session
*s
) {
115 mpls_socket_handle socket
= mpls_socket_create_tcp(g
->socket_handle
);
116 mpls_return_enum retval
;
118 LDP_ENTER(g
->user_data
, "ldp_session_attempt_setup");
120 if (mpls_socket_handle_verify(g
->socket_handle
, socket
) == MPLS_BOOL_FALSE
) {
123 if (mpls_socket_options(g
->socket_handle
, socket
, MPLS_SOCKOP_NONBLOCK
) ==
125 goto ldp_session_attempt_setup_error
;
128 retval
= mpls_socket_tcp_connect(g
->socket_handle
, socket
, &s
->remote_dest
);
131 case MPLS_NON_BLOCKING
:
133 LDP_TRACE_OUT(g
->user_data
,
134 "ldp_session_attempt_setup: MPLS_NON_BLOCKING\n");
135 mpls_socket_writelist_add(g
->socket_handle
, socket
, (void *)s
,
136 MPLS_SOCKET_TCP_CONNECT
);
141 LDP_TRACE_OUT(g
->user_data
,
142 "ldp_session_attempt_setup: MPLS_SUCCESS\n");
143 if (ldp_state_machine(g
, s
, NULL
, NULL
, LDP_EVENT_CONNECT
, NULL
,
144 NULL
) == MPLS_FAILURE
) {
145 goto ldp_session_attempt_setup_error
;
151 LDP_TRACE_OUT(g
->user_data
,
152 "ldp_session_attempt_setup: MPLS_FAILURE\n");
153 goto ldp_session_attempt_setup_error
;
159 LDP_EXIT(g
->user_data
, "ldp_session_attempt_setup");
162 ldp_session_attempt_setup_error
:
164 mpls_socket_close(g
->socket_handle
, socket
);
165 LDP_EXIT(g
->user_data
, "ldp_session_attempt_setup");
169 mpls_return_enum
ldp_session_create_active(ldp_global
* g
, ldp_adj
* a
)
171 mpls_return_enum retval
= MPLS_FAILURE
;
172 mpls_inet_addr
*addr
= NULL
;
173 ldp_session
*s
= NULL
;
176 MPLS_ASSERT(g
&& a
&& (!a
->session
));
178 LDP_ENTER(g
->user_data
, "ldp_session_create_active");
180 ap
= MPLS_LIST_HEAD(&g
->adj
);
182 if ((!mpls_inet_addr_compare(&ap
->remote_lsr_address
,
183 &a
->remote_lsr_address
)) &&
184 ap
->remote_label_space
== a
->remote_label_space
&&
185 a
->index
!= ap
->index
&& ap
->session
) {
186 ldp_adj_add_session(a
, ap
->session
);
187 retval
= MPLS_SUCCESS
;
188 goto ldp_session_create_active
;
190 ap
= MPLS_LIST_NEXT(&g
->adj
, ap
, _global
);
193 if ((s
= ldp_session_create())) {
194 if (a
->remote_transport_address
.type
!= MPLS_FAMILY_NONE
) {
195 addr
= &a
->remote_transport_address
;
197 addr
= &a
->remote_source_address
;
200 _ldp_global_add_session(g
, s
);
201 ldp_adj_add_session(a
, s
);
202 s
->state
= LDP_STATE_NON_EXIST
;
204 memcpy(&s
->remote_dest
.addr
, addr
, sizeof(mpls_inet_addr
));
205 s
->remote_dest
.port
= s
->cfg_peer_tcp_port
;
207 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
208 "ldp_session_create_active: (%d) changed to NON_EXIST\n", s
->index
);
210 if (ldp_session_attempt_setup(g
, s
) != MPLS_SUCCESS
) {
211 /* go into backoff */
212 ldp_session_backoff_start(g
, s
);
214 retval
= MPLS_SUCCESS
;
217 ldp_session_create_active
:
219 LDP_EXIT(g
->user_data
, "ldp_session_create_active");
223 ldp_session
*ldp_session_create_passive(ldp_global
* g
,
224 mpls_socket_handle socket
, mpls_dest
* from
)
226 ldp_session
*s
= NULL
;
230 LDP_ENTER(g
->user_data
, "ldp_session_create_passive");
232 if ((s
= ldp_session_create())) {
234 s
->state
= LDP_STATE_NON_EXIST
;
236 if (mpls_socket_options(g
->socket_handle
, socket
, MPLS_SOCKOP_NONBLOCK
) ==
238 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
239 "ldp_session_create_passive: (%d) changed to NON_EXIST\n", s
->index
);
240 _ldp_global_add_session(g
, s
);
242 ldp_session_delete(s
);
247 LDP_EXIT(g
->user_data
, "ldp_session_create_passive (%p)", s
);
252 void ldp_session_delete(ldp_session
* s
)
254 LDP_PRINT(NULL
, "session delete");
255 MPLS_REFCNT_ASSERT(s
, 0);
256 ldp_buf_delete(s
->tx_buffer
);
257 ldp_mesg_delete(s
->tx_message
);
258 mpls_free(MTYPE_LDP_SESSION
, s
);
261 mpls_return_enum
ldp_session_startup(ldp_global
* g
, ldp_session
* s
)
263 mpls_return_enum retval
= MPLS_FAILURE
;
266 void (*callback
) (mpls_timer_handle timer
, void *extra
, mpls_cfg_handle g
);
268 MPLS_ASSERT(s
&& g
&& (s
->oper_role
!= LDP_NONE
));
270 LDP_ENTER(g
->user_data
, "ldp_session_startup");
272 /* when we make it to operational, get rid of any backoff timers */
273 ldp_session_backoff_stop(g
, s
);
274 s
->state
= LDP_STATE_OPERATIONAL
;
275 s
->oper_up
= time(NULL
);
277 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
278 "ldp_session_startup: (%d) changed to OPERATIONAL\n", s
->index
);
281 * if configured to distribute addr messages walk the if table
282 * and send an addr message for each
284 if (g
->send_address_messages
) {
285 addr
= MPLS_LIST_HEAD(&g
->addr
);
287 /* only locally attached addrs will have a valid iff */
289 if (ldp_addr_send(g
, s
, &addr
->address
) != MPLS_SUCCESS
)
290 goto ldp_session_startup_end
;
292 addr
= MPLS_LIST_NEXT(&g
->addr
, addr
, _global
);
296 /* depending on the mode, grab a pointer to the correct callback */
297 switch (s
->oper_distribution_mode
) {
298 case LDP_DISTRIBUTION_ONDEMAND
:
299 callback
= ldp_label_request_initial_callback
;
301 case LDP_DISTRIBUTION_UNSOLICITED
:
302 callback
= ldp_label_mapping_initial_callback
;
309 * create a timer which will go about "chunking" the initial
310 * set of requests or mappings
313 s
->initial_distribution_timer
= mpls_timer_create(g
->timer_handle
,
314 MPLS_UNIT_SEC
, LDP_REQUEST_CHUNK
, (void *)s
, g
, callback
);
316 if (mpls_timer_handle_verify(g
->timer_handle
,
317 s
->initial_distribution_timer
) == MPLS_BOOL_FALSE
) {
318 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
320 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
321 "ldp_session_startup: initial distrib error(%d)\n", s
->index
);
323 /* timer error, we might as well shutdown the session, it's usless */
324 s
->shutdown_notif
= LDP_NOTIF_INTERNAL_ERROR
;
325 s
->shutdown_fatal
= MPLS_BOOL_TRUE
;
326 retval
= MPLS_FAILURE
;
328 mpls_timer_start(g
->timer_handle
, s
->initial_distribution_timer
,
330 retval
= MPLS_SUCCESS
;
333 ldp_session_startup_end
:
335 LDP_EXIT(g
->user_data
, "ldp_session_startup");
340 void ldp_session_shutdown(ldp_global
* g
, ldp_session
* s
, mpls_bool complete
)
343 ldp_attr
*attr
= NULL
;
344 ldp_attr
*nattr
= NULL
;
349 LDP_ENTER(g
->user_data
, "ldp_session_shutdown");
352 * hold a refcount so this session doesn't disappear on us
357 s
->state
= LDP_STATE_NONE
;
358 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_DEBUG
,
359 "ldp_session_shutdown: (%d) changed to NONE\n", s
->index
);
362 * kill the timers for the session
364 if (mpls_timer_handle_verify(g
->timer_handle
, s
->keepalive_recv_timer
) ==
366 mpls_timer_stop(g
->timer_handle
, s
->keepalive_recv_timer
);
367 mpls_timer_delete(g
->timer_handle
, s
->keepalive_recv_timer
);
368 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
369 s
->keepalive_recv_timer
= (mpls_timer_handle
) 0;
371 if (mpls_timer_handle_verify(g
->timer_handle
, s
->keepalive_send_timer
) ==
373 mpls_timer_stop(g
->timer_handle
, s
->keepalive_send_timer
);
374 mpls_timer_delete(g
->timer_handle
, s
->keepalive_send_timer
);
375 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
376 s
->keepalive_send_timer
= (mpls_timer_handle
) 0;
378 if (mpls_timer_handle_verify(g
->timer_handle
,s
->initial_distribution_timer
) ==
380 mpls_timer_stop(g
->timer_handle
, s
->initial_distribution_timer
);
381 mpls_timer_delete(g
->timer_handle
, s
->initial_distribution_timer
);
382 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
383 s
->initial_distribution_timer
= (mpls_timer_handle
) 0;
387 * get rid of the socket
389 if (mpls_socket_handle_verify(g
->socket_handle
, s
->socket
) ==
391 mpls_socket_readlist_del(g
->socket_handle
, s
->socket
);
392 mpls_socket_close(g
->socket_handle
, s
->socket
);
396 * get rid of out cached keepalive
398 if (s
->keepalive
!= NULL
) {
399 ldp_mesg_delete(s
->keepalive
);
403 ldp_session_backoff_stop(g
,s
);
405 attr
= MPLS_LIST_HEAD(&g
->attr
);
406 while (attr
!= NULL
) {
407 nattr
= MPLS_LIST_NEXT(&g
->attr
, attr
, _global
);
408 if (attr
->session
&& attr
->session
->index
== s
->index
) {
410 * ldp_attr_remove_complete removed everythig associated with the attr.
411 * in and out labels, and cross connects as well
413 ldp_attr_remove_complete(g
, attr
, complete
);
419 * clean up the addrs we created
421 while ((a
= (ldp_addr
*)mpls_link_list_head_data(&s
->addr_root
))) {
422 ldp_session_del_addr(g
, s
, a
);
426 * if we have an adj AND we are shuting down for a protocol reason, start a
427 * backoff timer, so we can try again in the near future
429 if ((complete
== MPLS_BOOL_TRUE
) || (s
->oper_role
!= LDP_ACTIVE
)) {
430 while ((ap
= MPLS_LIST_HEAD(&s
->adj_root
))) {
431 ldp_adj_del_session(ap
, s
);
434 if (s
->on_global
== MPLS_BOOL_TRUE
) {
435 _ldp_global_del_session(g
, s
);
438 if (s
->oper_role
== LDP_ACTIVE
) {
439 ldp_session_backoff_start(g
, s
);
444 * it is safe to release this refcnt now, if it is the last one, the
445 * session will be deleted (this will be the last one in the case of
446 * 'complete' == MPLS_BOOL_TRUE
448 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
450 LDP_EXIT(g
->user_data
, "ldp_session_shutdown");
453 mpls_return_enum
ldp_session_maintain_timer(ldp_global
* g
, ldp_session
* s
,
456 mpls_return_enum result
= MPLS_FAILURE
;
458 LDP_ENTER(g
->user_data
, "ldp_session_maintain_timer");
461 * all session keepalive maintainance comes through here (SEND and RECV)
463 if (flag
== LDP_KEEPALIVE_RECV
) {
464 mpls_timer_stop(g
->timer_handle
, s
->keepalive_recv_timer
);
465 result
= mpls_timer_start(g
->timer_handle
, s
->keepalive_recv_timer
,
468 mpls_timer_stop(g
->timer_handle
, s
->keepalive_send_timer
);
469 result
= mpls_timer_start(g
->timer_handle
, s
->keepalive_send_timer
,
470 MPLS_TIMER_REOCCURRING
);
473 LDP_EXIT(g
->user_data
, "ldp_session_maintain_timer");
478 void ldp_session_add_outlabel(ldp_session
* s
, ldp_outlabel
* o
)
482 MPLS_LIST_ADD_HEAD(&s
->outlabel_root
, o
, _session
, ldp_outlabel
);
483 _ldp_outlabel_add_session(o
, s
);
486 void ldp_session_del_outlabel(ldp_global
* g
,ldp_session
* s
, ldp_outlabel
* o
)
489 MPLS_LIST_REMOVE(&s
->outlabel_root
, o
, _session
);
490 _ldp_outlabel_del_session(o
);
491 MPLS_REFCNT_RELEASE2(g
, o
, ldp_outlabel_delete
);
494 mpls_return_enum
ldp_session_add_inlabel(ldp_global
* g
,ldp_session
* s
, ldp_inlabel
* i
)
498 if (mpls_link_list_add_tail(&s
->inlabel_root
, i
) == MPLS_SUCCESS
) {
499 if (_ldp_inlabel_add_session(i
, s
) == MPLS_SUCCESS
) {
502 mpls_link_list_remove_data(&s
->inlabel_root
, i
);
504 MPLS_REFCNT_RELEASE2(g
, i
, ldp_inlabel_delete
);
508 void ldp_session_del_inlabel(ldp_global
* g
,ldp_session
* s
, ldp_inlabel
* i
)
511 mpls_link_list_remove_data(&s
->inlabel_root
, i
);
512 _ldp_inlabel_del_session(i
, s
);
513 MPLS_REFCNT_RELEASE2(g
, i
, ldp_inlabel_delete
)
516 void _ldp_session_add_attr(ldp_session
* s
, ldp_attr
* a
)
520 MPLS_LIST_ADD_HEAD(&s
->attr_root
, a
, _session
, ldp_attr
);
523 void _ldp_session_del_attr(ldp_global
*g
, ldp_session
* s
, ldp_attr
* a
)
526 MPLS_LIST_REMOVE(&s
->attr_root
, a
, _session
);
527 MPLS_REFCNT_RELEASE2(g
, a
, ldp_attr_delete
);
530 mpls_return_enum
ldp_session_add_addr(ldp_global
*g
, ldp_session
* s
,
533 struct mpls_link_list_node
*lln
;
534 struct mpls_link_list_node
*llnp
;
540 lln
= mpls_link_list_node_create(a
);
542 if (_ldp_addr_add_session(a
, s
) == MPLS_SUCCESS
) {
543 MPLS_LINK_LIST_LOOP(&s
->addr_root
, data
, llnp
) {
544 if (data
->index
> a
->index
) {
545 mpls_link_list_add_node_before(&s
->addr_root
, llnp
, lln
);
550 mpls_link_list_add_node_tail(&s
->addr_root
, lln
);
553 mpls_link_list_node_delete(lln
);
555 MPLS_REFCNT_RELEASE2(g
, a
, ldp_addr_delete
);
559 void ldp_session_del_addr(ldp_global
*g
, ldp_session
* s
, ldp_addr
* a
) {
561 mpls_link_list_remove_data(&s
->addr_root
, a
);
562 _ldp_addr_del_session(a
, s
);
563 MPLS_REFCNT_RELEASE2(g
, a
, ldp_addr_delete
);
566 void _ldp_session_add_adj(ldp_session
* s
, ldp_adj
* a
)
569 struct in_addr lsr_address
;
574 s
->cfg_remote_in_ttl_less_domain
= a
->entity
->remote_in_ttl_less_domain
;
575 s
->cfg_distribution_mode
= a
->entity
->label_distribution_mode
;
576 s
->cfg_loop_detection_mode
= a
->entity
->loop_detection_mode
;
577 s
->cfg_label_request_count
= a
->entity
->label_request_count
;
578 s
->cfg_label_request_timer
= a
->entity
->label_request_timer
;
579 s
->cfg_label_space
= ldp_entity_label_space(a
->entity
);
580 s
->cfg_path_vector_limit
= a
->entity
->path_vector_limit
;
581 s
->cfg_hop_count_limit
= a
->entity
->hop_count_limit
;
582 s
->cfg_peer_tcp_port
= a
->entity
->remote_tcp_port
;
583 s
->cfg_keepalive
= a
->entity
->keepalive_timer
;
584 s
->cfg_max_pdu
= a
->entity
->max_pdu
;
586 lsr_address
.s_addr
= htonl(a
->remote_lsr_address
.u
.ipv4
);
587 sprintf(s
->session_name
, "%s:%d", inet_ntoa(lsr_address
),
588 a
->remote_label_space
);
589 s
->oper_role
= a
->role
;
591 ap
= MPLS_LIST_HEAD(&s
->adj_root
);
593 if (ap
->index
> a
->index
) {
594 MPLS_LIST_INSERT_BEFORE(&s
->adj_root
, ap
, a
, _session
);
597 ap
= MPLS_LIST_NEXT(&s
->adj_root
, ap
, _session
);
599 MPLS_LIST_ADD_TAIL(&s
->adj_root
, a
, _session
, ldp_adj
);
602 void _ldp_session_del_adj(ldp_session
* s
, ldp_adj
* a
)
605 MPLS_LIST_REMOVE(&s
->adj_root
, a
, _session
);
606 MPLS_REFCNT_RELEASE(a
, ldp_adj_delete
);
609 uint32_t _ldp_session_get_next_index()
611 uint32_t retval
= _ldp_session_next_index
;
613 _ldp_session_next_index
++;
614 if (retval
> _ldp_session_next_index
) {
615 _ldp_session_next_index
= 1;
620 mpls_return_enum
ldp_session_find_raddr_index(ldp_session
* s
, uint32_t index
,
623 struct mpls_link_list_node
*lln
;
626 if (s
&& index
> 0) {
627 /* because we sort our inserts by index, this lets us know
628 if we've "walked" past the end of the list */
630 if (mpls_link_list_isempty(&s
->addr_root
)) {
632 return MPLS_END_OF_LIST
;
635 if ((a
= (ldp_addr
*)mpls_link_list_tail_data(&s
->addr_root
))) {
636 if (a
->index
< index
) {
638 return MPLS_END_OF_LIST
;
642 MPLS_LINK_LIST_LOOP(&s
->addr_root
, a
, lln
) {
643 if (a
->index
== index
) {
653 mpls_return_enum
ldp_session_backoff_stop(ldp_global
* g
, ldp_session
* s
)
656 LDP_ENTER(g
->user_data
, "ldp_session_backoff_stop");
659 if (mpls_timer_handle_verify(g
->timer_handle
, s
->backoff_timer
) ==
662 mpls_timer_stop(g
->timer_handle
, s
->backoff_timer
);
663 mpls_timer_delete(g
->timer_handle
, s
->backoff_timer
);
664 s
->backoff_timer
= (mpls_timer_handle
) 0;
665 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
668 LDP_EXIT(g
->user_data
, "ldp_session_backoff_stop");
673 mpls_return_enum
ldp_session_backoff_start(ldp_global
* g
, ldp_session
* s
)
679 LDP_ENTER(g
->user_data
, "ldp_session_backoff_start");
681 valid
= mpls_timer_handle_verify(g
->timer_handle
,s
->backoff_timer
);
683 MPLS_ASSERT(valid
== MPLS_BOOL_FALSE
);
685 s
->backoff
+= g
->backoff_step
;
687 #if 0 /* if the above assert shouldn't be made this code should be executed */
689 /* this should never happen, but if so */
690 mpls_timer_stop(g
->timer_handle
, s
->backoff_timer
);
691 mpls_timer_delete(g
->timer_handle
, s
->backoff_timer
);
692 s
->backoff_timer
= (mpls_timer_handle
) 0;
693 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
696 if (!s
) { /* if we deleted session due to the above RELEASE */
697 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start-error");
703 s
->backoff_timer
= mpls_timer_create(g
->timer_handle
, MPLS_UNIT_SEC
,
704 s
->backoff
, (void *)s
, g
, ldp_session_backoff_callback
);
705 if (mpls_timer_handle_verify(g
->timer_handle
, s
->backoff_timer
) ==
708 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
709 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start-error");
713 if (mpls_timer_start(g
->timer_handle
, s
->backoff_timer
,
714 MPLS_TIMER_ONESHOT
) != MPLS_SUCCESS
) {
716 mpls_timer_delete(g
->timer_handle
, s
->backoff_timer
);
717 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
718 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start-error");
722 LDP_EXIT(g
->user_data
, "ldp_session_backoff_start");
727 ldp_session
*ldp_session_for_nexthop(ldp_nexthop
*nh
)
731 LDP_ENTER(g
->user_data
, "ldp_session_for_nexthop: 0x%04d", nh
->info
.type
);
733 if (nh
->info
.type
& MPLS_NH_IP
) {
734 LDP_PRINT(g
->user_data
, "ldp_session_for_nexthop-addr: %p %p %p\n",
735 nh
, nh
->addr
, nh
->addr
->session
);
736 if (nh
->addr
->session
) {
737 LDP_EXIT(g
->user_data
, "ldp_session_for_nexthop-addr: %p",
739 return nh
->addr
->session
;
742 if (nh
->info
.type
& MPLS_NH_IF
) {
743 ldp_session
*s
= NULL
;
744 if (nh
->iff
&& (s
= mpls_link_list_head_data(&nh
->iff
->session_root
))) {
745 LDP_EXIT(g
->user_data
, "ldp_session_for_nexthop-iff");
749 if (nh
->info
.type
& MPLS_NH_OUTSEGMENT
) {
752 LDP_EXIT(g
->user_data
, "ldp_session_for_nexthop-none");