Added comments to clarify the relationships
[mpls-ldp-portable.git] / ldp / ldp_peer.c
blobe9b7e7db115512eaa207aa80e7b6d00407177583
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 <sys/socket.h>
12 #include "ldp_struct.h"
13 #include "ldp_entity.h"
14 #include "ldp_peer.h"
15 #include "ldp_hello.h"
16 #include "ldp_buf.h"
17 #include "ldp_mesg.h"
19 #include "mpls_assert.h"
20 #include "mpls_fib_impl.h"
21 #include "mpls_ifmgr_impl.h"
22 #include "mpls_lock_impl.h"
23 #include "mpls_timer_impl.h"
24 #include "mpls_mm_impl.h"
25 #include "mpls_trace_impl.h"
27 uint32_t _ldp_sub_entity_next_index = 1;
29 void ldp_peer_retry_callback(mpls_timer_handle timer, void *extra,
30 mpls_cfg_handle handle)
32 ldp_peer *p = (ldp_peer *) extra;
33 ldp_global *g = (ldp_global*)handle;
35 LDP_ENTER(g->user_data, "ldp_peer_retry_callback");
37 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_TIMER,
38 "Peer Retry Timer fired: peer(%d)\n", p->index);
40 mpls_lock_get(g->global_lock);
42 /* JLEU: should I hold a copy to make sure this doens't fail? */
43 ldp_peer_retry_stop(g, p);
44 if (ldp_peer_startup(g, p) == MPLS_FAILURE) {
45 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_ERROR,
46 "Peer startup retry failure: peer (%d)\n", p->index);
49 mpls_lock_release(g->global_lock);
51 LDP_EXIT(g->user_data, "ldp_peer_retry_callback");
54 ldp_peer *ldp_peer_create()
56 ldp_peer *p = (ldp_peer *) mpls_malloc(sizeof(ldp_peer));
58 if (p) {
59 memset(p, 0, sizeof(ldp_peer));
60 MPLS_REFCNT_INIT(p, 0);
61 MPLS_LIST_ELEM_INIT(p, _global);
62 p->label_space = -1;
63 p->tx_buffer = ldp_buf_create(MPLS_PDUMAXLEN);
64 p->tx_message = ldp_mesg_create();
65 p->index = _ldp_peer_get_next_index();
67 p->oper_state = MPLS_OPER_DOWN;
68 p->target_role = LDP_ACTIVE;
70 return p;
73 void ldp_peer_delete(ldp_peer * p)
75 // LDP_PRINT(g->user_data,"peer delete\n");
76 MPLS_REFCNT_ASSERT(p, 0);
77 mpls_free(p->tx_buffer);
78 mpls_free(p->tx_message);
79 mpls_free(p);
82 mpls_return_enum ldp_peer_startup(ldp_global * g, ldp_peer * p)
84 ldp_entity *e = NULL;
85 mpls_if_handle handle;
86 mpls_bool unknown = MPLS_BOOL_FALSE;
87 mpls_fec dest;
88 mpls_fec entry[4];
90 MPLS_ASSERT(p != NULL && ((e = p->entity) != NULL));
92 LDP_ENTER(g->user_data, "ldp_peer_startup");
94 p->dest.port = e->remote_udp_port;
96 memcpy(&dest.u.host, &p->dest.addr, sizeof(mpls_inet_addr));
97 dest.type = MPLS_FEC_HOST;
99 if (mpls_fib_get_best_route(g->fib_handle, 4, &dest, entry) == 0) {
100 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
101 "ldp_peer_startup: exit(%d) no route to host\n", p->index);
103 goto ldp_peer_startup_retry;
106 if (entry[0].nh.type & MPLS_NH_IF) {
107 memcpy(&handle, &entry[0].nh.if_handle, sizeof(handle));
109 if (mpls_if_handle_verify(g->ifmgr_handle, handle) == MPLS_BOOL_FALSE) {
110 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
111 "ldp_peer_startup: exit(%d) no such if\n", p->index);
112 unknown = MPLS_BOOL_TRUE;
115 if (mpls_ifmgr_get_address(g->ifmgr_handle, handle,
116 &p->local_source_address, NULL, NULL) == MPLS_FAILURE) {
117 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
118 "ldp_peer_startup: exit(%d) ifmgr failure\n", p->index);
119 unknown = MPLS_BOOL_TRUE;
121 } else {
122 unknown = MPLS_BOOL_TRUE;
125 if (unknown == MPLS_BOOL_TRUE) {
126 goto ldp_peer_startup_retry;
129 if (p->target_role == LDP_ACTIVE) {
130 if (ldp_hello_send(g, e) == MPLS_FAILURE) {
131 goto ldp_peer_startup_retry;
135 p->oper_state = MPLS_OPER_UP;
137 LDP_EXIT(g->user_data, "ldp_peer_startup");
139 return MPLS_SUCCESS;
141 ldp_peer_startup_retry:
143 /* start a timer which will retry peer startup */
144 MPLS_REFCNT_HOLD(p);
145 p->oper_state = MPLS_OPER_DOWN;
146 p->no_route_to_peer_timer = mpls_timer_create(g->timer_handle, MPLS_UNIT_SEC,
147 g->no_route_to_peer_time, (void *)p, g, ldp_peer_retry_callback);
149 if (mpls_timer_handle_verify(g->timer_handle, p->no_route_to_peer_timer) ==
150 MPLS_BOOL_FALSE) {
151 MPLS_REFCNT_RELEASE(p, ldp_peer_delete);
152 LDP_EXIT(g->user_data, "ldp_peer_startup-error");
153 return MPLS_FAILURE;
155 mpls_timer_start(g->timer_handle, p->no_route_to_peer_timer, MPLS_TIMER_ONESHOT);
157 LDP_EXIT(g->user_data, "ldp_peer_startup");
159 return MPLS_SUCCESS;
162 void ldp_peer_retry_stop(ldp_global * g, ldp_peer * p)
164 MPLS_ASSERT(p != NULL);
166 LDP_ENTER(g->user_data, "ldp_peer_retry_stop");
168 if (mpls_timer_handle_verify(g->timer_handle, p->no_route_to_peer_timer) ==
169 MPLS_BOOL_TRUE) {
170 mpls_timer_stop(g->timer_handle, p->no_route_to_peer_timer);
171 mpls_timer_delete(g->timer_handle, p->no_route_to_peer_timer);
172 p->no_route_to_peer_timer = 0;
173 MPLS_REFCNT_RELEASE(p, ldp_peer_delete);
174 MPLS_ASSERT(p != NULL);
177 LDP_EXIT(g->user_data, "ldp_peer_retry_stop");
180 void ldp_peer_send_stop(ldp_global * g, ldp_peer * p)
182 ldp_entity *e = NULL;
184 MPLS_ASSERT(p != NULL && (e = p->entity) != NULL);
186 LDP_ENTER(g->user_data, "ldp_peer_send_stop");
188 if (mpls_timer_handle_verify(g->timer_handle, p->hellotime_send_timer) ==
189 MPLS_BOOL_TRUE) {
190 mpls_timer_stop(g->timer_handle, p->hellotime_send_timer);
191 mpls_timer_delete(g->timer_handle, p->hellotime_send_timer);
192 p->hellotime_send_timer_duration = 0;
193 p->hellotime_send_timer = 0;
194 MPLS_REFCNT_RELEASE(e, ldp_entity_delete);
195 MPLS_ASSERT(e != NULL);
197 if (p->hello != NULL) {
198 ldp_mesg_delete(p->hello);
199 p->hello = NULL;
202 LDP_EXIT(g->user_data, "ldp_peer_send_stop");
205 mpls_return_enum ldp_peer_shutdown(ldp_global * g, ldp_peer * p)
207 LDP_ENTER(g->user_data, "ldp_peer_shutdown");
209 p->oper_state = MPLS_OPER_DOWN;
210 ldp_peer_send_stop(g, p);
211 ldp_peer_retry_stop(g, p);
213 LDP_EXIT(g->user_data, "ldp_peer_shutdown");
214 return MPLS_SUCCESS;
217 mpls_bool ldp_peer_is_active(ldp_peer * p)
219 if (p && p->entity && p->entity->admin_state == MPLS_ADMIN_ENABLE)
220 return MPLS_BOOL_TRUE;
222 return MPLS_BOOL_FALSE;
225 mpls_return_enum _ldp_peer_add_entity(ldp_peer * p, ldp_entity * e)
227 if (p && e) {
228 MPLS_REFCNT_HOLD(e);
229 p->entity = e;
230 return MPLS_SUCCESS;
232 return MPLS_FAILURE;
235 mpls_return_enum _ldp_peer_del_entity(ldp_peer * p)
237 if (p && p->entity) {
238 MPLS_REFCNT_RELEASE(p->entity, ldp_entity_delete);
239 p->entity = NULL;
240 return MPLS_SUCCESS;
242 return MPLS_FAILURE;
245 ldp_entity *ldp_peer_get_entity(ldp_peer * p)
247 return p->entity;
250 uint32_t _ldp_peer_get_next_index()
252 uint32_t retval = _ldp_sub_entity_next_index;
254 _ldp_sub_entity_next_index++;
255 if (retval > _ldp_sub_entity_next_index) {
256 _ldp_sub_entity_next_index = 1;
258 return retval;