3 * Copyright (C) James R. Leu 2000
6 * This software is covered under the LGPL, for more
7 * info check out http://www.gnu.org/copyleft/lgpl.html
11 #include <sys/socket.h>
12 #include "ldp_struct.h"
13 #include "ldp_entity.h"
15 #include "ldp_hello.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
));
59 memset(p
, 0, sizeof(ldp_peer
));
60 MPLS_REFCNT_INIT(p
, 0);
61 MPLS_LIST_ELEM_INIT(p
, _global
);
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
;
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
);
82 mpls_return_enum
ldp_peer_startup(ldp_global
* g
, ldp_peer
* p
)
85 mpls_if_handle handle
;
86 mpls_bool unknown
= MPLS_BOOL_FALSE
;
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
;
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");
141 ldp_peer_startup_retry
:
143 /* start a timer which will retry peer startup */
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
) ==
151 MPLS_REFCNT_RELEASE(p
, ldp_peer_delete
);
152 LDP_EXIT(g
->user_data
, "ldp_peer_startup-error");
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");
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
) ==
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
) ==
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
);
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");
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
)
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
);
245 ldp_entity
*ldp_peer_get_entity(ldp_peer
* p
)
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;