FECs are now inserted in the tree upon creation
[mpls-ldp-portable.git] / ldp / ldp_session.c
blob6cebafdc6136bff0b3bea323acec43d509f4e437
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_inet_addr addr;
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) {
283 addr.u.ipv4 = 0L;
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) ==
287 MPLS_BOOL_TRUE) {
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;
301 break;
302 case LDP_DISTRIBUTION_UNSOLICITED:
303 callback = ldp_label_mapping_initial_callback;
304 break;
305 default:
306 MPLS_ASSERT(0);
310 * create a timer which will go about "chunking" the initial
311 * set of requests or mappings
313 MPLS_REFCNT_HOLD(s);
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;
328 } else {
329 mpls_timer_start(g->timer_handle, s->initial_distribution_timer,
330 MPLS_TIMER_ONESHOT);
331 retval = MPLS_SUCCESS;
334 ldp_session_startup_end:
336 LDP_EXIT(g->user_data, "ldp_session_startup");
338 return retval;
341 void ldp_session_shutdown(ldp_global * g, ldp_session * s, mpls_bool complete)
343 ldp_addr *a = NULL;
344 ldp_attr *attr = NULL;
345 ldp_attr *temp_attr = NULL;
346 ldp_adj* ap;
348 MPLS_ASSERT(s);
350 LDP_ENTER(g->user_data, "ldp_session_shutdown");
353 * hold a refcount so this session doesn't disappear on us
354 * while cleaning up
356 MPLS_REFCNT_HOLD(s);
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) ==
366 MPLS_BOOL_TRUE) {
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) ==
373 MPLS_BOOL_TRUE) {
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) ==
380 MPLS_BOOL_TRUE) {
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) ==
391 MPLS_BOOL_TRUE) {
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);
401 s->keepalive = NULL;
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) {
409 temp_attr = attr;
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);
416 } else {
417 temp_attr = NULL;
419 attr = MPLS_LIST_NEXT(&g->attr, attr, _global);
420 if (temp_attr)
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);
443 } else {
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,
460 int flag)
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,
472 MPLS_TIMER_ONESHOT);
473 } else {
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");
481 return result;
484 void ldp_session_add_outlabel(ldp_session * s, ldp_outlabel * o)
486 MPLS_ASSERT(s && o);
487 MPLS_REFCNT_HOLD(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)
494 MPLS_ASSERT(s && 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)
502 MPLS_ASSERT(s && i);
503 MPLS_REFCNT_HOLD(i);
504 if (mpls_link_list_add_tail(&s->inlabel_root, i) == MPLS_SUCCESS) {
505 if (_ldp_inlabel_add_session(i, s) == MPLS_SUCCESS) {
506 return MPLS_SUCCESS;
508 mpls_link_list_remove_data(&s->inlabel_root, i);
510 MPLS_REFCNT_RELEASE(i, ldp_inlabel_delete);
511 return MPLS_FAILURE;
514 void ldp_session_del_inlabel(ldp_session * s, ldp_inlabel * i)
516 MPLS_ASSERT(s && 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)
524 MPLS_ASSERT(s && a);
525 MPLS_REFCNT_HOLD(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)
531 MPLS_ASSERT(s && 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,
537 ldp_addr * a)
539 struct mpls_link_list_node *lln;
540 struct mpls_link_list_node *llnp;
541 ldp_addr *data;
543 MPLS_ASSERT(s && a);
545 MPLS_REFCNT_HOLD(a);
546 lln = mpls_link_list_node_create(a);
547 if (lln) {
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);
552 return MPLS_SUCCESS;
556 mpls_link_list_add_node_tail(&s->addr_root, lln);
557 return MPLS_SUCCESS;
559 mpls_link_list_node_delete(lln);
561 MPLS_REFCNT_RELEASE2(g, a, ldp_addr_delete);
562 return MPLS_FAILURE;
565 void ldp_session_del_addr(ldp_global *g, ldp_session * s, ldp_addr * a) {
566 MPLS_ASSERT(s && 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)
574 ldp_adj *ap = NULL;
575 struct in_addr lsr_address;
577 MPLS_ASSERT(s && a);
578 MPLS_REFCNT_HOLD(a);
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);
598 while (ap) {
599 if (ap->index > a->index) {
600 MPLS_LIST_INSERT_BEFORE(&s->adj_root, ap, a, _session);
601 return;
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)
610 MPLS_ASSERT(s && 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;
623 return retval;
626 mpls_return_enum ldp_session_find_raddr_index(ldp_session * s, uint32_t index,
627 ldp_addr ** addr)
629 struct mpls_link_list_node *lln;
630 ldp_addr *a = NULL;
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)) {
637 *addr = NULL;
638 return MPLS_END_OF_LIST;
641 if ((a = (ldp_addr*)mpls_link_list_tail_data(&s->addr_root))) {
642 if (a->index < index) {
643 *addr = NULL;
644 return MPLS_END_OF_LIST;
648 MPLS_LINK_LIST_LOOP(&s->addr_root, a, lln) {
649 if (a->index == index) {
650 *addr = a;
651 return MPLS_SUCCESS;
655 *addr = NULL;
656 return MPLS_FAILURE;
659 mpls_return_enum ldp_session_backoff_stop(ldp_global * g, ldp_session * s)
662 LDP_ENTER(g->user_data, "ldp_session_backoff_stop");
664 s->backoff = 0;
665 if (mpls_timer_handle_verify(g->timer_handle, s->backoff_timer) ==
666 MPLS_BOOL_TRUE) {
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");
676 return MPLS_SUCCESS;
679 mpls_return_enum ldp_session_backoff_start(ldp_global * g, ldp_session * s)
681 mpls_bool valid;
683 MPLS_ASSERT(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");
704 return MPLS_FAILURE;
706 #endif
708 MPLS_REFCNT_HOLD(s);
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) ==
712 MPLS_BOOL_FALSE) {
714 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
715 LDP_EXIT(g->user_data, "ldp_session_backoff_start-error");
716 return MPLS_FAILURE;
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");
725 return MPLS_FAILURE;
728 LDP_EXIT(g->user_data, "ldp_session_backoff_start");
730 return MPLS_SUCCESS;
733 ldp_session *ldp_session_for_nexthop(ldp_nexthop *nh)
735 MPLS_ASSERT(nh);
737 if (nh->info.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);
740 if (s) {
741 return s;
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 return s;
750 if (nh->info.type & MPLS_NH_OUTSEGMENT) {
751 MPLS_ASSERT(0);
753 return NULL;