📄 ldp_session.c
字号:
/* * Copyright (C) James R. Leu 2000 * jleu@mindspring.com * * This software is covered under the LGPL, for more * info check out http://www.gnu.org/copyleft/lgpl.html */#include <stdlib.h>#include "ldp_struct.h"#include "ldp_outlabel.h"#include "ldp_session.h"#include "ldp_entity.h"#include "ldp_inlabel.h"#include "ldp_outlabel.h"#include "ldp_addr.h"#include "ldp_attr.h"#include "ldp_adj.h"#include "ldp_mesg.h"#include "ldp_buf.h"#include "ldp_inet_addr.h"#include "ldp_global.h"#include "ldp_state_machine.h"#include "ldp_label_rel_with.h"#include "ldp_label_request.h"#include "ldp_label_mapping.h"#include "mpls_refcnt.h"#include "mpls_assert.h"#include "mpls_mm_impl.h"#include "mpls_timer_impl.h"#include "mpls_socket_impl.h"#include "mpls_trace_impl.h"#include "mpls_ifmgr_impl.h"#include "mpls_policy_impl.h"#include "mpls_lock_impl.h"static uint32_t _ldp_session_next_index = 1;mpls_return_enum ldp_session_attempt_setup(ldp_global *g, ldp_session *s);mpls_return_enum ldp_session_backoff_stop(ldp_global * g, ldp_session * s);static void ldp_session_backoff_callback(mpls_timer_handle timer, void *extra, mpls_cfg_handle handle){ ldp_session *s = (ldp_session *)extra; ldp_global *g = (ldp_global*)handle; LDP_ENTER(g->user_data, "ldp_session_backoff"); LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_TIMER, "Session Backoff Timer fired: session(%s)\n", s->session_name); mpls_lock_get(g->global_lock); s->backoff_timer = 0; if (s->oper_role == LDP_ACTIVE) { if (ldp_session_attempt_setup(g, s) != MPLS_SUCCESS) { s->backoff += g->backoff_step; s->backoff_timer = timer; mpls_timer_start(g->timer_handle, timer, MPLS_TIMER_ONESHOT); LDP_EXIT(g->user_data, "ldp_session_backoff-error"); goto ldp_session_backoff_end; } } else if (s->oper_role == LDP_PASSIVE) { /* this is a passive session that never received an init, kill it * session current on the global list and the timer holds a refcnt. * shutdown takes this session off of the global list, so when the * timer refcnt is released the session will be deleted */ ldp_session_shutdown(g, s, MPLS_BOOL_TRUE); } else { MPLS_ASSERT(0); } mpls_timer_stop(g->timer_handle, timer); mpls_timer_delete(g->timer_handle, timer); MPLS_REFCNT_RELEASE(s, ldp_session_delete);ldp_session_backoff_end: mpls_lock_release(g->global_lock); LDP_EXIT(g->user_data, "ldp_session_backoff");}ldp_session *ldp_session_create(){ ldp_session *s = (ldp_session *) mpls_malloc(sizeof(ldp_session)); if (s) { memset(s, 0, sizeof(ldp_session)); MPLS_REFCNT_INIT(s, 0); MPLS_LIST_ELEM_INIT(s, _global); MPLS_LIST_INIT(&s->outlabel_root, ldp_outlabel); MPLS_LIST_INIT(&s->attr_root, ldp_attr); MPLS_LIST_INIT(&s->adj_root, ldp_adj); mpls_link_list_init(&s->inlabel_root); mpls_link_list_init(&s->addr_root); s->on_global = MPLS_BOOL_FALSE; s->tx_buffer = ldp_buf_create(MPLS_PDUMAXLEN); s->tx_message = ldp_mesg_create(); s->index = _ldp_session_get_next_index(); s->oper_role = LDP_NONE; } return s;}mpls_return_enum ldp_session_attempt_setup(ldp_global *g, ldp_session *s) { mpls_socket_handle socket = mpls_socket_create_tcp(g->socket_handle); mpls_return_enum retval; LDP_ENTER(g->user_data, "ldp_session_attempt_setup"); if (mpls_socket_handle_verify(g->socket_handle, socket) == MPLS_BOOL_FALSE) { return MPLS_FAILURE; } if (mpls_socket_options(g->socket_handle, socket, MPLS_SOCKOP_NONBLOCK) == MPLS_FAILURE) { goto ldp_session_attempt_setup_error; } retval = mpls_socket_tcp_connect(g->socket_handle, socket, &s->remote_dest); switch (retval) { case MPLS_NON_BLOCKING: { LDP_TRACE_OUT(g->user_data, "ldp_session_attempt_setup: MPLS_NON_BLOCKING\n"); mpls_socket_writelist_add(g->socket_handle, socket, (void *)s, MPLS_SOCKET_TCP_CONNECT); break; } case MPLS_SUCCESS: { LDP_TRACE_OUT(g->user_data, "ldp_session_attempt_setup: MPLS_SUCCESS\n"); if (ldp_state_machine(g, s, NULL, NULL, LDP_EVENT_CONNECT, NULL, NULL) == MPLS_FAILURE) { goto ldp_session_attempt_setup_error; } break; } default: { LDP_TRACE_OUT(g->user_data, "ldp_session_attempt_setup: MPLS_FAILURE\n"); goto ldp_session_attempt_setup_error; } break; } s->socket = socket; LDP_EXIT(g->user_data, "ldp_session_attempt_setup"); return MPLS_SUCCESS;ldp_session_attempt_setup_error: mpls_socket_close(g->socket_handle, socket); LDP_EXIT(g->user_data, "ldp_session_attempt_setup"); return MPLS_FAILURE;}mpls_return_enum ldp_session_create_active(ldp_global * g, ldp_adj * a){ mpls_return_enum retval = MPLS_FAILURE; mpls_inet_addr *addr = NULL; ldp_session *s = NULL; ldp_adj* ap; MPLS_ASSERT(g && a && (!a->session)); LDP_ENTER(g->user_data, "ldp_session_create_active"); ap = MPLS_LIST_HEAD(&g->adj); while (ap) { if ((!mpls_inet_addr_compare(&ap->remote_lsr_address, &a->remote_lsr_address)) && ap->remote_label_space == a->remote_label_space && a->index != ap->index && ap->session) { ldp_adj_add_session(a, ap->session); retval = MPLS_SUCCESS; goto ldp_session_create_active; } ap = MPLS_LIST_NEXT(&g->adj, ap, _global); } if ((s = ldp_session_create())) { if (a->remote_transport_address.type != MPLS_FAMILY_NONE) { addr = &a->remote_transport_address; } else { addr = &a->remote_source_address; } _ldp_global_add_session(g, s); ldp_adj_add_session(a, s); s->state = LDP_STATE_NON_EXIST; memcpy(&s->remote_dest.addr, addr, sizeof(mpls_inet_addr)); s->remote_dest.port = s->cfg_peer_tcp_port; LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG, "ldp_session_create_active: (%d) changed to NON_EXIST\n", s->index); if (ldp_session_attempt_setup(g, s) != MPLS_SUCCESS) { /* go into backoff */ ldp_session_backoff_start(g, s); } retval = MPLS_SUCCESS; }ldp_session_create_active: LDP_EXIT(g->user_data, "ldp_session_create_active"); return retval;}ldp_session *ldp_session_create_passive(ldp_global * g, mpls_socket_handle socket, mpls_dest * from){ ldp_session *s = NULL; MPLS_ASSERT(g); LDP_ENTER(g->user_data, "ldp_session_create_passive"); if ((s = ldp_session_create())) { s->socket = socket; s->state = LDP_STATE_NON_EXIST; if (mpls_socket_options(g->socket_handle, socket, MPLS_SOCKOP_NONBLOCK) == MPLS_SUCCESS) { LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG, "ldp_session_create_passive: (%d) changed to NON_EXIST\n", s->index); _ldp_global_add_session(g, s); } else { ldp_session_delete(s); s = NULL; } } LDP_EXIT(g->user_data, "ldp_session_create_passive (%p)", s); return s;}void ldp_session_delete(ldp_session * s){ LDP_PRINT(NULL, "session delete"); MPLS_REFCNT_ASSERT(s, 0); mpls_free(s);}mpls_return_enum ldp_session_startup(ldp_global * g, ldp_session * s){ mpls_return_enum retval = MPLS_FAILURE; ldp_addr *addr; void (*callback) (mpls_timer_handle timer, void *extra, mpls_cfg_handle g); MPLS_ASSERT(s && g && (s->oper_role != LDP_NONE)); LDP_ENTER(g->user_data, "ldp_session_startup"); /* when we make it to operational, get rid of any backoff timers */ ldp_session_backoff_stop(g, s); s->state = LDP_STATE_OPERATIONAL; s->oper_up = time(NULL); LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG, "ldp_session_startup: (%d) changed to OPERATIONAL\n", s->index); /* * if configured to distribute addr messages walk the if table * and send an addr message for each */ if (g->send_address_messages) { addr = MPLS_LIST_HEAD(&g->addr); while (addr) { /* only locally attached addrs will have a valid iff */ if (addr->iff) { if (ldp_addr_send(g, s, &addr->address) != MPLS_SUCCESS) goto ldp_session_startup_end; } addr = MPLS_LIST_NEXT(&g->addr, addr, _global); } } /* depending on the mode, grab a pointer to the correct callback */ switch (s->oper_distribution_mode) { case LDP_DISTRIBUTION_ONDEMAND: callback = ldp_label_request_initial_callback; break; case LDP_DISTRIBUTION_UNSOLICITED: callback = ldp_label_mapping_initial_callback; break; default: MPLS_ASSERT(0); } /* * create a timer which will go about "chunking" the initial * set of requests or mappings */ MPLS_REFCNT_HOLD(s); s->initial_distribution_timer = mpls_timer_create(g->timer_handle, MPLS_UNIT_SEC, LDP_REQUEST_CHUNK, (void *)s, g, callback); if (mpls_timer_handle_verify(g->timer_handle, s->initial_distribution_timer) == MPLS_BOOL_FALSE) { MPLS_REFCNT_RELEASE(s, ldp_session_delete); LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG, "ldp_session_startup: initial distrib error(%d)\n", s->index); /* timer error, we might as well shutdown the session, it's usless */ s->shutdown_notif = LDP_NOTIF_INTERNAL_ERROR; s->shutdown_fatal = MPLS_BOOL_TRUE; retval = MPLS_FAILURE; } else { mpls_timer_start(g->timer_handle, s->initial_distribution_timer, MPLS_TIMER_ONESHOT); retval = MPLS_SUCCESS; }ldp_session_startup_end: LDP_EXIT(g->user_data, "ldp_session_startup"); return retval;}void ldp_session_shutdown(ldp_global * g, ldp_session * s, mpls_bool complete){ ldp_addr *a = NULL; ldp_attr *attr = NULL; ldp_attr *nattr = NULL; ldp_adj* ap; MPLS_ASSERT(s); LDP_ENTER(g->user_data, "ldp_session_shutdown"); /* * hold a refcount so this session doesn't disappear on us * while cleaning up */ MPLS_REFCNT_HOLD(s); s->state = LDP_STATE_NONE; LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG, "ldp_session_shutdown: (%d) changed to NONE\n", s->index); /* * kill the timers for the session */ if (mpls_timer_handle_verify(g->timer_handle, s->keepalive_recv_timer) == MPLS_BOOL_TRUE) { mpls_timer_stop(g->timer_handle, s->keepalive_recv_timer); mpls_timer_delete(g->timer_handle, s->keepalive_recv_timer); MPLS_REFCNT_RELEASE(s, ldp_session_delete); s->keepalive_recv_timer = (mpls_timer_handle) 0; } if (mpls_timer_handle_verify(g->timer_handle, s->keepalive_send_timer) == MPLS_BOOL_TRUE) { mpls_timer_stop(g->timer_handle, s->keepalive_send_timer); mpls_timer_delete(g->timer_handle, s->keepalive_send_timer); MPLS_REFCNT_RELEASE(s, ldp_session_delete); s->keepalive_send_timer = (mpls_timer_handle) 0; } if (mpls_timer_handle_verify(g->timer_handle,s->initial_distribution_timer) == MPLS_BOOL_TRUE) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -