No longer do we use the ifmgr to walk the addresses attached to this
[mpls-ldp-portable.git] / ldp / ldp_session.c
blob72b3d3652bd25345f1db854021dd4501bedcc30b
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 if_handle */
285 if (mpls_if_handle_verify(g->ifmgr_handle, addr->if_handle) ==
286 MPLS_BOOL_TRUE) {
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;
298 break;
299 case LDP_DISTRIBUTION_UNSOLICITED:
300 callback = ldp_label_mapping_initial_callback;
301 break;
302 default:
303 MPLS_ASSERT(0);
307 * create a timer which will go about "chunking" the initial
308 * set of requests or mappings
310 MPLS_REFCNT_HOLD(s);
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;
325 } else {
326 mpls_timer_start(g->timer_handle, s->initial_distribution_timer,
327 MPLS_TIMER_ONESHOT);
328 retval = MPLS_SUCCESS;
331 ldp_session_startup_end:
333 LDP_EXIT(g->user_data, "ldp_session_startup");
335 return retval;
338 void ldp_session_shutdown(ldp_global * g, ldp_session * s, mpls_bool complete)
340 ldp_addr *a = NULL;
341 ldp_attr *attr = NULL;
342 ldp_attr *temp_attr = NULL;
343 ldp_adj* ap;
345 MPLS_ASSERT(s);
347 LDP_ENTER(g->user_data, "ldp_session_shutdown");
350 * hold a refcount so this session doesn't disappear on us
351 * while cleaning up
353 MPLS_REFCNT_HOLD(s);
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) ==
363 MPLS_BOOL_TRUE) {
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) ==
370 MPLS_BOOL_TRUE) {
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) ==
377 MPLS_BOOL_TRUE) {
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) ==
388 MPLS_BOOL_TRUE) {
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);
398 s->keepalive = NULL;
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) {
406 temp_attr = attr;
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);
413 } else {
414 temp_attr = NULL;
416 attr = MPLS_LIST_NEXT(&g->attr, attr, _global);
417 if (temp_attr)
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);
440 } else {
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,
457 int flag)
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,
469 MPLS_TIMER_ONESHOT);
470 } else {
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");
478 return result;
481 void ldp_session_add_outlabel(ldp_session * s, ldp_outlabel * o)
483 MPLS_ASSERT(s && o);
484 MPLS_REFCNT_HOLD(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)
491 MPLS_ASSERT(s && 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)
499 MPLS_ASSERT(s && i);
500 MPLS_REFCNT_HOLD(i);
501 if (mpls_link_list_add_tail(&s->inlabel_root, i) == MPLS_SUCCESS) {
502 if (_ldp_inlabel_add_session(i, s) == MPLS_SUCCESS) {
503 return MPLS_SUCCESS;
505 mpls_link_list_remove_data(&s->inlabel_root, i);
507 MPLS_REFCNT_RELEASE(i, ldp_inlabel_delete);
508 return MPLS_FAILURE;
511 void ldp_session_del_inlabel(ldp_session * s, ldp_inlabel * i)
513 MPLS_ASSERT(s && 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)
521 MPLS_ASSERT(s && a);
522 MPLS_REFCNT_HOLD(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)
528 MPLS_ASSERT(s && 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,
534 ldp_addr * a)
536 struct mpls_link_list_node *lln;
537 struct mpls_link_list_node *llnp;
538 ldp_addr *data;
540 MPLS_ASSERT(s && a);
542 MPLS_REFCNT_HOLD(a);
543 lln = mpls_link_list_node_create(a);
544 if (lln) {
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);
549 return MPLS_SUCCESS;
553 mpls_link_list_add_node_tail(&s->addr_root, lln);
554 return MPLS_SUCCESS;
556 mpls_link_list_node_delete(lln);
558 MPLS_REFCNT_RELEASE2(g, a, ldp_addr_delete);
559 return MPLS_FAILURE;
562 void ldp_session_del_addr(ldp_global *g, ldp_session * s, ldp_addr * a) {
563 MPLS_ASSERT(s && 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)
571 ldp_adj *ap = NULL;
572 struct in_addr lsr_address;
574 MPLS_ASSERT(s && a);
575 MPLS_REFCNT_HOLD(a);
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);
595 while (ap) {
596 if (ap->index > a->index) {
597 MPLS_LIST_INSERT_BEFORE(&s->adj_root, ap, a, _session);
598 return;
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)
607 MPLS_ASSERT(s && 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;
620 return retval;
623 mpls_return_enum ldp_session_find_raddr_index(ldp_session * s, uint32_t index,
624 ldp_addr ** addr)
626 struct mpls_link_list_node *lln;
627 ldp_addr *a = NULL;
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)) {
634 *addr = NULL;
635 return MPLS_END_OF_LIST;
638 if ((a = (ldp_addr*)mpls_link_list_tail_data(&s->addr_root))) {
639 if (a->index < index) {
640 *addr = NULL;
641 return MPLS_END_OF_LIST;
645 MPLS_LINK_LIST_LOOP(&s->addr_root, a, lln) {
646 if (a->index == index) {
647 *addr = a;
648 return MPLS_SUCCESS;
652 *addr = NULL;
653 return MPLS_FAILURE;
656 mpls_return_enum ldp_session_backoff_stop(ldp_global * g, ldp_session * s)
659 LDP_ENTER(g->user_data, "ldp_session_backoff_stop");
661 s->backoff = 0;
662 if (mpls_timer_handle_verify(g->timer_handle, s->backoff_timer) ==
663 MPLS_BOOL_TRUE) {
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");
673 return MPLS_SUCCESS;
676 mpls_return_enum ldp_session_backoff_start(ldp_global * g, ldp_session * s)
678 mpls_bool valid;
680 MPLS_ASSERT(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");
701 return MPLS_FAILURE;
703 #endif
705 MPLS_REFCNT_HOLD(s);
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) ==
709 MPLS_BOOL_FALSE) {
711 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
712 LDP_EXIT(g->user_data, "ldp_session_backoff_start-error");
713 return MPLS_FAILURE;
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");
722 return MPLS_FAILURE;
725 LDP_EXIT(g->user_data, "ldp_session_backoff_start");
727 return MPLS_SUCCESS;
730 ldp_session *ldp_session_for_nexthop(ldp_nexthop *nh)
732 MPLS_ASSERT(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);
737 if (s) {
738 return s;
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))) {
744 return s;
747 if (nh->info.type & MPLS_NH_OUTSEGMENT) {
748 MPLS_ASSERT(0);
750 return NULL;