You cannot possible compile the LSR (or the LDP) lib without a porting
[mpls-ldp-portable.git] / ldp / ldp_session.c
blob37f1ae21412933929742c38f44ce7fda901f80ab
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(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_session * s, ldp_addr * a)
538 struct mpls_link_list_node *lln;
539 struct mpls_link_list_node *llnp;
540 ldp_addr *data;
542 MPLS_ASSERT(s && a);
544 MPLS_REFCNT_HOLD(a);
545 lln = mpls_link_list_node_create(a);
546 if (lln) {
547 if (_ldp_addr_add_session(a, s) == MPLS_SUCCESS) {
548 MPLS_LINK_LIST_LOOP(&s->addr_root, data, llnp) {
549 if (data->index > a->index) {
550 mpls_link_list_add_node_before(&s->addr_root, llnp, lln);
551 return MPLS_SUCCESS;
555 mpls_link_list_add_node_tail(&s->addr_root, lln);
556 return MPLS_SUCCESS;
558 mpls_link_list_node_delete(lln);
560 MPLS_REFCNT_RELEASE(a, ldp_addr_delete);
561 return MPLS_FAILURE;
564 void ldp_session_del_addr(ldp_session * s, ldp_addr * a) {
565 MPLS_ASSERT(s && a);
566 mpls_link_list_remove_data(&s->addr_root, a);
567 _ldp_addr_del_session(a, s);
568 MPLS_REFCNT_RELEASE(a, ldp_addr_delete);
571 void _ldp_session_add_adj(ldp_session * s, ldp_adj * a)
573 ldp_adj *ap = NULL;
574 struct in_addr lsr_address;
576 MPLS_ASSERT(s && a);
577 MPLS_REFCNT_HOLD(a);
579 s->cfg_remote_in_ttl_less_domain = a->entity->remote_in_ttl_less_domain;
580 s->cfg_distribution_mode = a->entity->label_distribution_mode;
581 s->cfg_loop_detection_mode = a->entity->loop_detection_mode;
582 s->cfg_label_request_count = a->entity->label_request_count;
583 s->cfg_label_request_timer = a->entity->label_request_timer;
584 s->cfg_label_space = ldp_entity_label_space(a->entity);
585 s->cfg_path_vector_limit = a->entity->path_vector_limit;
586 s->cfg_hop_count_limit = a->entity->hop_count_limit;
587 s->cfg_peer_tcp_port = a->entity->remote_tcp_port;
588 s->cfg_keepalive = a->entity->keepalive_timer;
589 s->cfg_max_pdu = a->entity->max_pdu;
591 lsr_address.s_addr = htonl(a->remote_lsr_address.u.ipv4);
592 sprintf(s->session_name, "%s:%d", inet_ntoa(lsr_address),
593 a->remote_label_space);
594 s->oper_role = a->role;
596 ap = MPLS_LIST_HEAD(&s->adj_root);
597 while (ap) {
598 if (ap->index > a->index) {
599 MPLS_LIST_INSERT_BEFORE(&s->adj_root, ap, a, _session);
600 return;
602 ap = MPLS_LIST_NEXT(&s->adj_root, ap, _session);
604 MPLS_LIST_ADD_TAIL(&s->adj_root, a, _session, ldp_adj);
607 void _ldp_session_del_adj(ldp_session * s, ldp_adj * a)
609 MPLS_ASSERT(s && a);
610 MPLS_LIST_REMOVE(&s->adj_root, a, _session);
611 MPLS_REFCNT_RELEASE(a, ldp_adj_delete);
614 uint32_t _ldp_session_get_next_index()
616 uint32_t retval = _ldp_session_next_index;
618 _ldp_session_next_index++;
619 if (retval > _ldp_session_next_index) {
620 _ldp_session_next_index = 1;
622 return retval;
625 mpls_return_enum ldp_session_find_raddr_index(ldp_session * s, uint32_t index,
626 ldp_addr ** addr)
628 struct mpls_link_list_node *lln;
629 ldp_addr *a = NULL;
631 if (s && index > 0) {
632 /* because we sort our inserts by index, this lets us know
633 if we've "walked" past the end of the list */
635 if (mpls_link_list_isempty(&s->addr_root)) {
636 *addr = NULL;
637 return MPLS_END_OF_LIST;
640 if ((a = (ldp_addr*)mpls_link_list_tail_data(&s->addr_root))) {
641 if (a->index < index) {
642 *addr = NULL;
643 return MPLS_END_OF_LIST;
647 MPLS_LINK_LIST_LOOP(&s->addr_root, a, lln) {
648 if (a->index == index) {
649 *addr = a;
650 return MPLS_SUCCESS;
654 *addr = NULL;
655 return MPLS_FAILURE;
658 mpls_return_enum ldp_session_backoff_stop(ldp_global * g, ldp_session * s)
661 LDP_ENTER(g->user_data, "ldp_session_backoff_stop");
663 s->backoff = 0;
664 if (mpls_timer_handle_verify(g->timer_handle, s->backoff_timer) ==
665 MPLS_BOOL_TRUE) {
667 mpls_timer_stop(g->timer_handle, s->backoff_timer);
668 mpls_timer_delete(g->timer_handle, s->backoff_timer);
669 s->backoff_timer = (mpls_timer_handle) 0;
670 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
673 LDP_EXIT(g->user_data, "ldp_session_backoff_stop");
675 return MPLS_SUCCESS;
678 mpls_return_enum ldp_session_backoff_start(ldp_global * g, ldp_session * s)
680 mpls_bool valid;
682 MPLS_ASSERT(s);
684 LDP_ENTER(g->user_data, "ldp_session_backoff_start");
686 valid = mpls_timer_handle_verify(g->timer_handle,s->backoff_timer);
688 MPLS_ASSERT(valid == MPLS_BOOL_FALSE);
690 s->backoff += g->backoff_step;
692 #if 0 /* if the above assert shouldn't be made this code should be executed */
694 /* this should never happen, but if so */
695 mpls_timer_stop(g->timer_handle, s->backoff_timer);
696 mpls_timer_delete(g->timer_handle, s->backoff_timer);
697 s->backoff_timer = (mpls_timer_handle) 0;
698 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
701 if (!s) { /* if we deleted session due to the above RELEASE */
702 LDP_EXIT(g->user_data, "ldp_session_backoff_start-error");
703 return MPLS_FAILURE;
705 #endif
707 MPLS_REFCNT_HOLD(s);
708 s->backoff_timer = mpls_timer_create(g->timer_handle, MPLS_UNIT_SEC,
709 s->backoff, (void *)s, g, ldp_session_backoff_callback);
710 if (mpls_timer_handle_verify(g->timer_handle, s->backoff_timer) ==
711 MPLS_BOOL_FALSE) {
713 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
714 LDP_EXIT(g->user_data, "ldp_session_backoff_start-error");
715 return MPLS_FAILURE;
718 if (mpls_timer_start(g->timer_handle, s->backoff_timer,
719 MPLS_TIMER_ONESHOT) != MPLS_SUCCESS) {
721 mpls_timer_delete(g->timer_handle, s->backoff_timer);
722 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
723 LDP_EXIT(g->user_data, "ldp_session_backoff_start-error");
724 return MPLS_FAILURE;
727 LDP_EXIT(g->user_data, "ldp_session_backoff_start");
729 return MPLS_SUCCESS;