/* * 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 #include #include #include #include "ldp_struct.h" #include "ldp_assert.h" #include "ldp_session.h" #include "ldp_global.h" #include "ldp_entity.h" #include "ldp_hello.h" #include "ldp_peer.h" #include "ldp_adj.h" #include "ldp_if.h" #include "ldp_inet_addr.h" #include "ldp_msg.h" #include "ldp_cfg.h" #include "ldp_mm_impl.h" #include "ldp_timer_impl.h" #include "ldp_socket_impl.h" #include "ldp_trace_impl.h" static uint32_t _ldp_entity_next_index = 1; ldp_entity* ldp_entity_create() { ldp_entity* e = (ldp_entity*)ldp_malloc(sizeof(ldp_entity)); if(e) { memset(e,0,sizeof(ldp_entity)); LDP_REFCNT_INIT(e,0); LDP_LIST_INIT(&e->session_root,ldp_session); LDP_LIST_INIT(&e->adj_root,ldp_adj); LDP_LIST_ELEM_INIT(e,_global); e->entity_type = LDP_UNKNOWN; if(LDP_ENTITY_DEF_TRANS_ADDR != 0) { e->transport_address.protocol = AF_INET; e->transport_address.u.ipv4 = LDP_ENTITY_DEF_TRANS_ADDR; } e->protocol_version = LDP_ENTITY_DEF_PROTO_VER; e->remote_tcp_port = LDP_ENTITY_DEF_REMOTE_TCP; e->remote_udp_port = LDP_ENTITY_DEF_REMOTE_UDP; e->max_pdu = LDP_ENTITY_DEF_MAX_PDU; e->keepalive_timer = LDP_ENTITY_DEF_KEEPALIVE_TIMER; e->keepalive_interval = LDP_ENTITY_DEF_KEEPALIVE_INTERVAL; e->hellotime_timer = LDP_ENTITY_DEF_HELLOTIME_TIMER; e->hellotime_interval = LDP_ENTITY_DEF_HELLOTIME_INTERVAL; e->session_setup_count = LDP_ENTITY_DEF_SESSIONSETUP_COUNT; e->session_backoff_timer = LDP_ENTITY_DEF_SESSION_BACKOFF_TIMER; e->label_distribution_mode = LDP_ENTITY_DEF_DISTRIBUTION_MODE; e->path_vector_limit = LDP_ENTITY_DEF_PATHVECTOR_LIMIT; e->hop_count_limit = LDP_ENTITY_DEF_HOPCOUNT_LIMIT; e->label_request_timer = LDP_ENTITY_DEF_REQUEST_COUNT; e->label_request_count = LDP_ENTITY_DEF_REQUEST_TIMER; e->require_hop_count = LDP_ENTITY_DEF_REQUIRE_HOPCOUNT; e->inherit_flag = LDP_ENTITY_DEF_INHERIT_FLAG; e->index = _ldp_entity_get_next_index(); e->admin_state = LDP_DISABLE; e->remote_in_ttl_less_domain = LDP_FALSE; } return e; } void ldp_entity_delete(ldp_entity* e) { // LDP_PRINT(g->user_data,"entity delete\n"); LDP_REFCNT_ASSERT(e,0); ldp_free(e); } int ldp_entity_label_space(ldp_entity* e) { if(e) { switch(e->entity_type) { case LDP_DIRECT: return e->p.iff->range->label_space; case LDP_INDIRECT: return e->p.peer->range->label_space; default: LDP_ASSERT(0); } } return -1; } ldp_bool ldp_entity_is_active(ldp_entity* e) { if(e && e->admin_state == LDP_ENABLE) return LDP_TRUE; return LDP_FALSE; } ldp_bool ldp_entity_is_ready(ldp_entity* e) { if(e) { switch(e->entity_type) { case LDP_DIRECT: if(e->p.iff && e->p.iff->range) return LDP_TRUE; break; case LDP_INDIRECT: if(e->p.peer && e->p.peer->range) return LDP_TRUE; break; default: LDP_ASSERT(0); } } return LDP_FALSE; } ldp_return_enum ldp_entity_startup(ldp_global* g,ldp_entity* e) { ldp_return_enum retval = LDP_FAILURE; LDP_ASSERT(g != NULL && e != NULL && e->p.iff != NULL); LDP_ENTER(g->user_data,"ldp_entity_startup"); if(e->inherit_flag & LDP_ENTITY_CFG_TRANS_ADDR) { memcpy(&e->transport_address,&g->transport_address,sizeof(ldp_inet_addr)); } if(e->inherit_flag & LDP_ENTITY_CFG_KEEPALIVE_TIMER) { e->keepalive_timer = g->keepalive_timer; } if(e->inherit_flag & LDP_ENTITY_CFG_KEEPALIVE_INTERVAL) { e->keepalive_interval = g->keepalive_interval; } if(e->inherit_flag & LDP_ENTITY_CFG_HELLOTIME_TIMER) { e->hellotime_timer = g->hellotime_timer; } if(e->inherit_flag & LDP_ENTITY_CFG_HELLOTIME_INTERVAL) { e->hellotime_interval = g->hellotime_interval; } e->loop_detection_mode = g->loop_detection_mode; switch(e->entity_type) { case LDP_DIRECT: retval = ldp_if_startup(g,e->p.iff); break; case LDP_INDIRECT: retval = ldp_peer_startup(g,e->p.peer); break; default: LDP_ASSERT(0); } if(retval == LDP_SUCCESS) e->admin_state = LDP_ENABLE; LDP_EXIT(g->user_data,"ldp_entity_startup"); return retval; } ldp_return_enum ldp_entity_shutdown(ldp_global* g,ldp_entity* e,int flag) { ldp_adj* adj = NULL; LDP_ASSERT(g != NULL && e != NULL); LDP_ENTER(g->user_data,"ldp_entity_shutdown"); /* flag is only set if the global entity is being disabled */ if(!flag) { e->admin_state = LDP_DISABLE; } switch(e->entity_type) { case LDP_DIRECT: if(ldp_if_shutdown(g,e->p.iff) == LDP_FAILURE) { LDP_PRINT(g->user_data,"ldp_entity_shutdown: shutting down if\n"); } break; case LDP_INDIRECT: if(ldp_peer_shutdown(g,e->p.peer) == LDP_FAILURE) { LDP_PRINT(g->user_data,"ldp_entity_shutdown: shutting down peer\n"); } break; default: LDP_ASSERT(0); } LDP_LIST_REMOVE_HEAD(&e->adj_root,adj,_entity) while(adj != NULL) { ldp_adj_shutdown(g,adj); /* ldp_adj_shutdown() does a ldp_entity_del_adj(e,adj) */ LDP_LIST_REMOVE_HEAD(&e->adj_root,adj,_entity) } LDP_EXIT(g->user_data,"ldp_entity_shutdown"); return LDP_SUCCESS; } uint32_t _ldp_entity_get_next_index() { uint32_t retval = _ldp_entity_next_index; _ldp_entity_next_index++; if(retval > _ldp_entity_next_index++) { _ldp_entity_next_index = 1; } return retval; } ldp_return_enum ldp_entity_add_if(ldp_entity* e,ldp_if* i) { if(e && i) { if(e->entity_type != LDP_UNKNOWN) { return LDP_FAILURE; } e->entity_type = LDP_DIRECT; LDP_REFCNT_HOLD(i); e->p.iff = i; e->sub_index = i->index; _ldp_if_add_entity(i,e); return LDP_SUCCESS; } return LDP_FAILURE; } ldp_return_enum ldp_entity_del_if(ldp_entity* e) { if(e && e->entity_type == LDP_DIRECT && e->p.iff) { _ldp_if_del_entity(e->p.iff); LDP_REFCNT_RELEASE(e->p.iff,ldp_if_delete); e->p.iff = NULL; e->entity_type = LDP_UNKNOWN; e->sub_index = 0; return LDP_SUCCESS; } return LDP_FAILURE; } ldp_return_enum ldp_entity_add_peer(ldp_entity* e,ldp_peer* p) { if(e) { if(e->entity_type != LDP_UNKNOWN) { return LDP_FAILURE; } e->entity_type = LDP_INDIRECT; LDP_REFCNT_HOLD(p); e->p.peer = p; e->sub_index = p->index; _ldp_peer_add_entity(p,e); return LDP_SUCCESS; } return LDP_FAILURE; } ldp_return_enum ldp_entity_del_peer(ldp_entity* e) { if(e && e->entity_type == LDP_INDIRECT && e->p.peer) { _ldp_peer_del_entity(e->p.peer); LDP_REFCNT_RELEASE(e->p.peer,ldp_peer_delete); e->p.peer = NULL; e->entity_type = LDP_UNKNOWN; e->sub_index = 0; return LDP_SUCCESS; } return LDP_FAILURE; } ldp_return_enum _ldp_entity_add_session(ldp_entity* e,ldp_session* s) { if(e && s) { LDP_REFCNT_HOLD(s); LDP_LIST_ADD_HEAD(&e->session_root,s,_entity,ldp_session); _ldp_session_add_entity(s,e); return LDP_SUCCESS; } return LDP_FAILURE; } ldp_return_enum _ldp_entity_del_session(ldp_entity* e,ldp_session* s) { if(e && s) { LDP_LIST_REMOVE(&e->session_root,s,_entity); _ldp_session_del_entity(s); LDP_REFCNT_RELEASE(s,ldp_session_delete); return LDP_SUCCESS; } return LDP_FAILURE; } ldp_return_enum ldp_entity_add_adj(ldp_entity* e,ldp_adj* a) { if(e && a) { LDP_REFCNT_HOLD(a); LDP_LIST_ADD_HEAD(&e->adj_root,a,_entity,ldp_adj); _ldp_adj_add_entity(a,e); return LDP_SUCCESS; } return LDP_FAILURE; } ldp_return_enum ldp_entity_del_adj(ldp_entity* e,ldp_adj* a) { if(e && a) { LDP_LIST_REMOVE(&e->adj_root,a,_entity); _ldp_adj_del_entity(a); LDP_REFCNT_RELEASE(a,ldp_adj_delete); return LDP_SUCCESS; } return LDP_FAILURE; } ldp_adj *ldp_entity_find_adj(ldp_entity* e,ldp_msg* msg) { ldp_adj* a = NULL; ldp_inet_addr lsraddr; int labelspace; if(e == NULL) return NULL; if(ldp_msg_hdr_get_labelspace(msg,&labelspace) == LDP_FAILURE || ldp_msg_hdr_get_lsraddr(msg,&lsraddr) == LDP_FAILURE) return NULL; a = LDP_LIST_HEAD(&e->adj_root); while(a != NULL) { if(a->remote_label_space == labelspace && (ldp_inet_addr_is_equal(&lsraddr,&a->remote_lsr_address) == LDP_TRUE)) return a; a = LDP_LIST_NEXT(&e->adj_root,a,_entity); } return NULL; }