From: Vasu Dasari <vdasari@gmail.com>
[mpls-ldp-portable.git] / ldp / ldp_session.c
bloba72a96b5c5fefb70aae2744bce33ac6a3051d4fc
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(
93 MTYPE_LDP_SESSION, sizeof(ldp_session));
95 if (s) {
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;
111 return s;
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) {
121 return MPLS_FAILURE;
123 if (mpls_socket_options(g->socket_handle, socket, MPLS_SOCKOP_NONBLOCK) ==
124 MPLS_FAILURE) {
125 goto ldp_session_attempt_setup_error;
128 retval = mpls_socket_tcp_connect(g->socket_handle, socket, &s->remote_dest);
130 switch (retval) {
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);
137 break;
139 case MPLS_SUCCESS:
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;
147 break;
149 default:
151 LDP_TRACE_OUT(g->user_data,
152 "ldp_session_attempt_setup: MPLS_FAILURE\n");
153 goto ldp_session_attempt_setup_error;
155 break;
158 s->socket = socket;
159 LDP_EXIT(g->user_data, "ldp_session_attempt_setup");
160 return MPLS_SUCCESS;
162 ldp_session_attempt_setup_error:
164 mpls_socket_close(g->socket_handle, socket);
165 LDP_EXIT(g->user_data, "ldp_session_attempt_setup");
166 return MPLS_FAILURE;
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;
174 ldp_adj* ap;
176 MPLS_ASSERT(g && a && (!a->session));
178 LDP_ENTER(g->user_data, "ldp_session_create_active");
180 ap = MPLS_LIST_HEAD(&g->adj);
181 while (ap) {
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;
196 } else {
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");
220 return retval;
223 ldp_session *ldp_session_create_passive(ldp_global * g,
224 mpls_socket_handle socket, mpls_dest * from)
226 ldp_session *s = NULL;
228 MPLS_ASSERT(g);
230 LDP_ENTER(g->user_data, "ldp_session_create_passive");
232 if ((s = ldp_session_create())) {
233 s->socket = socket;
234 s->state = LDP_STATE_NON_EXIST;
236 if (mpls_socket_options(g->socket_handle, socket, MPLS_SOCKOP_NONBLOCK) ==
237 MPLS_SUCCESS) {
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);
241 } else {
242 ldp_session_delete(s);
243 s = NULL;
247 LDP_EXIT(g->user_data, "ldp_session_create_passive (%p)", s);
249 return 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;
264 ldp_addr *addr;
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);
286 while (addr) {
287 /* only locally attached addrs will have a valid iff */
288 if (addr->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;
300 break;
301 case LDP_DISTRIBUTION_UNSOLICITED:
302 callback = ldp_label_mapping_initial_callback;
303 break;
304 default:
305 MPLS_ASSERT(0);
309 * create a timer which will go about "chunking" the initial
310 * set of requests or mappings
312 MPLS_REFCNT_HOLD(s);
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;
327 } else {
328 mpls_timer_start(g->timer_handle, s->initial_distribution_timer,
329 MPLS_TIMER_ONESHOT);
330 retval = MPLS_SUCCESS;
333 ldp_session_startup_end:
335 LDP_EXIT(g->user_data, "ldp_session_startup");
337 return retval;
340 void ldp_session_shutdown(ldp_global * g, ldp_session * s, mpls_bool complete)
342 ldp_addr *a = NULL;
343 ldp_attr *attr = NULL;
344 ldp_attr *nattr = NULL;
345 ldp_adj* ap;
347 MPLS_ASSERT(s);
349 LDP_ENTER(g->user_data, "ldp_session_shutdown");
352 * hold a refcount so this session doesn't disappear on us
353 * while cleaning up
355 MPLS_REFCNT_HOLD(s);
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) ==
365 MPLS_BOOL_TRUE) {
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) ==
372 MPLS_BOOL_TRUE) {
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) ==
379 MPLS_BOOL_TRUE) {
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) ==
390 MPLS_BOOL_TRUE) {
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);
400 s->keepalive = NULL;
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);
415 attr = nattr;
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);
437 } else {
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,
454 int flag)
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,
466 MPLS_TIMER_ONESHOT);
467 } else {
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");
475 return result;
478 void ldp_session_add_outlabel(ldp_session * s, ldp_outlabel * o)
480 MPLS_ASSERT(s && o);
481 MPLS_REFCNT_HOLD(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)
488 MPLS_ASSERT(s && 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)
496 MPLS_ASSERT(s && i);
497 MPLS_REFCNT_HOLD(i);
498 if (mpls_link_list_add_tail(&s->inlabel_root, i) == MPLS_SUCCESS) {
499 if (_ldp_inlabel_add_session(i, s) == MPLS_SUCCESS) {
500 return MPLS_SUCCESS;
502 mpls_link_list_remove_data(&s->inlabel_root, i);
504 MPLS_REFCNT_RELEASE2(g, i, ldp_inlabel_delete);
505 return MPLS_FAILURE;
508 void ldp_session_del_inlabel(ldp_global * g,ldp_session * s, ldp_inlabel * i)
510 MPLS_ASSERT(s && 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)
518 MPLS_ASSERT(s && a);
519 MPLS_REFCNT_HOLD(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)
525 MPLS_ASSERT(s && 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,
531 ldp_addr * a)
533 struct mpls_link_list_node *lln;
534 struct mpls_link_list_node *llnp;
535 ldp_addr *data;
537 MPLS_ASSERT(s && a);
539 MPLS_REFCNT_HOLD(a);
540 lln = mpls_link_list_node_create(a);
541 if (lln) {
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);
546 return MPLS_SUCCESS;
550 mpls_link_list_add_node_tail(&s->addr_root, lln);
551 return MPLS_SUCCESS;
553 mpls_link_list_node_delete(lln);
555 MPLS_REFCNT_RELEASE2(g, a, ldp_addr_delete);
556 return MPLS_FAILURE;
559 void ldp_session_del_addr(ldp_global *g, ldp_session * s, ldp_addr * a) {
560 MPLS_ASSERT(s && 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)
568 ldp_adj *ap = NULL;
569 struct in_addr lsr_address;
571 MPLS_ASSERT(s && a);
572 MPLS_REFCNT_HOLD(a);
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);
592 while (ap) {
593 if (ap->index > a->index) {
594 MPLS_LIST_INSERT_BEFORE(&s->adj_root, ap, a, _session);
595 return;
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)
604 MPLS_ASSERT(s && 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;
617 return retval;
620 mpls_return_enum ldp_session_find_raddr_index(ldp_session * s, uint32_t index,
621 ldp_addr ** addr)
623 struct mpls_link_list_node *lln;
624 ldp_addr *a = NULL;
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)) {
631 *addr = NULL;
632 return MPLS_END_OF_LIST;
635 if ((a = (ldp_addr*)mpls_link_list_tail_data(&s->addr_root))) {
636 if (a->index < index) {
637 *addr = NULL;
638 return MPLS_END_OF_LIST;
642 MPLS_LINK_LIST_LOOP(&s->addr_root, a, lln) {
643 if (a->index == index) {
644 *addr = a;
645 return MPLS_SUCCESS;
649 *addr = NULL;
650 return MPLS_FAILURE;
653 mpls_return_enum ldp_session_backoff_stop(ldp_global * g, ldp_session * s)
656 LDP_ENTER(g->user_data, "ldp_session_backoff_stop");
658 s->backoff = 0;
659 if (mpls_timer_handle_verify(g->timer_handle, s->backoff_timer) ==
660 MPLS_BOOL_TRUE) {
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");
670 return MPLS_SUCCESS;
673 mpls_return_enum ldp_session_backoff_start(ldp_global * g, ldp_session * s)
675 mpls_bool valid;
677 MPLS_ASSERT(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");
698 return MPLS_FAILURE;
700 #endif
702 MPLS_REFCNT_HOLD(s);
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) ==
706 MPLS_BOOL_FALSE) {
708 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
709 LDP_EXIT(g->user_data, "ldp_session_backoff_start-error");
710 return MPLS_FAILURE;
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");
719 return MPLS_FAILURE;
722 LDP_EXIT(g->user_data, "ldp_session_backoff_start");
724 return MPLS_SUCCESS;
727 ldp_session *ldp_session_for_nexthop(ldp_nexthop *nh)
729 MPLS_ASSERT(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",
738 nh->addr->session);
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");
746 return s;
749 if (nh->info.type & MPLS_NH_OUTSEGMENT) {
750 MPLS_ASSERT(0);
752 LDP_EXIT(g->user_data, "ldp_session_for_nexthop-none");
753 return NULL;