Add additional comments
[mpls-ldp-portable.git] / ldp / ldp_session.c
blob192a1b01c02502ab11cbd56435e54ece01519444
2 /*
3 * Copyright (C) James R. Leu 2000
4 * jleu@mindspring.com
6 * This software is covered under the LGPL, for more
7 * info check out http://www.gnu.org/copyleft/lgpl.html
8 */
10 #include <stdlib.h>
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"
17 #include "ldp_addr.h"
18 #include "ldp_attr.h"
19 #include "ldp_adj.h"
20 #include "ldp_mesg.h"
21 #include "ldp_buf.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);
57 s->backoff_timer = 0;
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);
75 } else {
76 MPLS_ASSERT(0);
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));
94 if (s) {
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;
110 return s;
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) {
120 return MPLS_FAILURE;
122 if (mpls_socket_options(g->socket_handle, socket, MPLS_SOCKOP_NONBLOCK) ==
123 MPLS_FAILURE) {
124 goto ldp_session_attempt_setup_error;
127 retval = mpls_socket_tcp_connect(g->socket_handle, socket, &s->remote_dest);
129 switch (retval) {
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);
136 break;
138 case MPLS_SUCCESS:
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;
146 break;
148 default:
150 LDP_TRACE_OUT(g->user_data,
151 "ldp_session_attempt_setup: MPLS_FAILURE\n");
152 goto ldp_session_attempt_setup_error;
154 break;
157 s->socket = socket;
158 LDP_EXIT(g->user_data, "ldp_session_attempt_setup");
159 return MPLS_SUCCESS;
161 ldp_session_attempt_setup_error:
163 mpls_socket_close(g->socket_handle, socket);
164 LDP_EXIT(g->user_data, "ldp_session_attempt_setup");
165 return MPLS_FAILURE;
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;
173 ldp_adj* ap;
175 MPLS_ASSERT(g && a && (!a->session));
177 LDP_ENTER(g->user_data, "ldp_session_create_active");
179 ap = MPLS_LIST_HEAD(&g->adj);
180 while (ap) {
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;
195 } else {
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");
219 return retval;
222 ldp_session *ldp_session_create_passive(ldp_global * g,
223 mpls_socket_handle socket, mpls_dest * from)
225 ldp_session *s = NULL;
227 MPLS_ASSERT(g);
229 LDP_ENTER(g->user_data, "ldp_session_create_passive");
231 if ((s = ldp_session_create())) {
232 s->socket = socket;
233 s->state = LDP_STATE_NON_EXIST;
235 if (mpls_socket_options(g->socket_handle, socket, MPLS_SOCKOP_NONBLOCK) ==
236 MPLS_SUCCESS) {
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);
240 } else {
241 ldp_session_delete(s);
242 s = NULL;
246 LDP_EXIT(g->user_data, "ldp_session_create_passive (%p)", s);
248 return s;
251 void ldp_session_delete(ldp_session * s)
253 fprintf(stderr,"session delete\n");
254 MPLS_REFCNT_ASSERT(s, 0);
255 mpls_free(s);
258 mpls_return_enum ldp_session_startup(ldp_global * g, ldp_session * s)
260 mpls_return_enum retval = MPLS_FAILURE;
261 ldp_addr *addr;
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);
283 while (addr) {
284 /* only locally attached addrs will have a valid iff */
285 if (addr->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;
297 break;
298 case LDP_DISTRIBUTION_UNSOLICITED:
299 callback = ldp_label_mapping_initial_callback;
300 break;
301 default:
302 MPLS_ASSERT(0);
306 * create a timer which will go about "chunking" the initial
307 * set of requests or mappings
309 MPLS_REFCNT_HOLD(s);
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;
324 } else {
325 mpls_timer_start(g->timer_handle, s->initial_distribution_timer,
326 MPLS_TIMER_ONESHOT);
327 retval = MPLS_SUCCESS;
330 ldp_session_startup_end:
332 LDP_EXIT(g->user_data, "ldp_session_startup");
334 return retval;
337 void ldp_session_shutdown(ldp_global * g, ldp_session * s, mpls_bool complete)
339 ldp_addr *a = NULL;
340 ldp_attr *attr = NULL;
341 ldp_attr *temp_attr = NULL;
342 ldp_adj* ap;
344 MPLS_ASSERT(s);
346 LDP_ENTER(g->user_data, "ldp_session_shutdown");
349 * hold a refcount so this session doesn't disappear on us
350 * while cleaning up
352 MPLS_REFCNT_HOLD(s);
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) ==
362 MPLS_BOOL_TRUE) {
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) ==
369 MPLS_BOOL_TRUE) {
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) ==
376 MPLS_BOOL_TRUE) {
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) ==
387 MPLS_BOOL_TRUE) {
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);
397 s->keepalive = NULL;
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) {
405 temp_attr = attr;
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);
412 } else {
413 temp_attr = NULL;
415 attr = MPLS_LIST_NEXT(&g->attr, attr, _global);
416 if (temp_attr)
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);
439 } else {
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,
456 int flag)
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,
468 MPLS_TIMER_ONESHOT);
469 } else {
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");
477 return result;
480 void ldp_session_add_outlabel(ldp_session * s, ldp_outlabel * o)
482 MPLS_ASSERT(s && o);
483 MPLS_REFCNT_HOLD(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)
490 MPLS_ASSERT(s && 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)
498 MPLS_ASSERT(s && i);
499 MPLS_REFCNT_HOLD(i);
500 if (mpls_link_list_add_tail(&s->inlabel_root, i) == MPLS_SUCCESS) {
501 if (_ldp_inlabel_add_session(i, s) == MPLS_SUCCESS) {
502 return MPLS_SUCCESS;
504 mpls_link_list_remove_data(&s->inlabel_root, i);
506 MPLS_REFCNT_RELEASE(i, ldp_inlabel_delete);
507 return MPLS_FAILURE;
510 void ldp_session_del_inlabel(ldp_session * s, ldp_inlabel * i)
512 MPLS_ASSERT(s && 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)
520 MPLS_ASSERT(s && a);
521 MPLS_REFCNT_HOLD(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)
527 MPLS_ASSERT(s && 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,
533 ldp_addr * a)
535 struct mpls_link_list_node *lln;
536 struct mpls_link_list_node *llnp;
537 ldp_addr *data;
539 MPLS_ASSERT(s && a);
541 MPLS_REFCNT_HOLD(a);
542 lln = mpls_link_list_node_create(a);
543 if (lln) {
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);
548 return MPLS_SUCCESS;
552 mpls_link_list_add_node_tail(&s->addr_root, lln);
553 return MPLS_SUCCESS;
555 mpls_link_list_node_delete(lln);
557 MPLS_REFCNT_RELEASE2(g, a, ldp_addr_delete);
558 return MPLS_FAILURE;
561 void ldp_session_del_addr(ldp_global *g, ldp_session * s, ldp_addr * a) {
562 MPLS_ASSERT(s && 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)
570 ldp_adj *ap = NULL;
571 struct in_addr lsr_address;
573 MPLS_ASSERT(s && a);
574 MPLS_REFCNT_HOLD(a);
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);
594 while (ap) {
595 if (ap->index > a->index) {
596 MPLS_LIST_INSERT_BEFORE(&s->adj_root, ap, a, _session);
597 return;
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)
606 MPLS_ASSERT(s && 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;
619 return retval;
622 mpls_return_enum ldp_session_find_raddr_index(ldp_session * s, uint32_t index,
623 ldp_addr ** addr)
625 struct mpls_link_list_node *lln;
626 ldp_addr *a = NULL;
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)) {
633 *addr = NULL;
634 return MPLS_END_OF_LIST;
637 if ((a = (ldp_addr*)mpls_link_list_tail_data(&s->addr_root))) {
638 if (a->index < index) {
639 *addr = NULL;
640 return MPLS_END_OF_LIST;
644 MPLS_LINK_LIST_LOOP(&s->addr_root, a, lln) {
645 if (a->index == index) {
646 *addr = a;
647 return MPLS_SUCCESS;
651 *addr = NULL;
652 return MPLS_FAILURE;
655 mpls_return_enum ldp_session_backoff_stop(ldp_global * g, ldp_session * s)
658 LDP_ENTER(g->user_data, "ldp_session_backoff_stop");
660 s->backoff = 0;
661 if (mpls_timer_handle_verify(g->timer_handle, s->backoff_timer) ==
662 MPLS_BOOL_TRUE) {
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");
672 return MPLS_SUCCESS;
675 mpls_return_enum ldp_session_backoff_start(ldp_global * g, ldp_session * s)
677 mpls_bool valid;
679 MPLS_ASSERT(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");
700 return MPLS_FAILURE;
702 #endif
704 MPLS_REFCNT_HOLD(s);
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) ==
708 MPLS_BOOL_FALSE) {
710 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
711 LDP_EXIT(g->user_data, "ldp_session_backoff_start-error");
712 return MPLS_FAILURE;
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");
721 return MPLS_FAILURE;
724 LDP_EXIT(g->user_data, "ldp_session_backoff_start");
726 return MPLS_SUCCESS;
729 ldp_session *ldp_session_for_nexthop(ldp_nexthop *nh)
731 MPLS_ASSERT(nh);
733 LDP_ENTER(g->user_data, "ldp_session_for_nexthop: 0x%04d", nh->info.type);
735 if (nh->info.type & MPLS_NH_IP) {
736 LDP_PRINT(g->user_data, "ldp_session_for_nexthop-addr: %p %p %p\n",
737 nh, nh->addr, nh->addr->session);
738 if (nh->addr->session) {
739 LDP_EXIT(g->user_data, "ldp_session_for_nexthop-addr: %p",
740 nh->addr->session);
741 return nh->addr->session;
744 if (nh->info.type & MPLS_NH_IF) {
745 ldp_session *s = NULL;
746 if (nh->iff && (s = mpls_link_list_head_data(&nh->iff->session_root))) {
747 LDP_EXIT(g->user_data, "ldp_session_for_nexthop-iff");
748 return s;
751 if (nh->info.type & MPLS_NH_OUTSEGMENT) {
752 MPLS_ASSERT(0);
754 LDP_EXIT(g->user_data, "ldp_session_for_nexthop-none");
755 return NULL;