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_global.h"
14 #include "ldp_session.h"
15 #include "ldp_hello.h"
16 #include "ldp_global.h"
17 #include "ldp_entity.h"
20 #include "mpls_mm_impl.h"
21 #include "mpls_assert.h"
22 #include "mpls_timer_impl.h"
23 #include "mpls_lock_impl.h"
24 #include "mpls_trace_impl.h"
26 static uint32_t _ldp_adj_next_index
= 1;
28 ldp_adj
*ldp_adj_create(mpls_inet_addr
* source
, mpls_inet_addr
* lsraddr
,
29 int labelspace
, int remote_hellotime
,
30 mpls_inet_addr
* remote_transport_address
, uint32_t remote_csn
)
32 ldp_adj
*a
= (ldp_adj
*) mpls_malloc(sizeof(ldp_adj
));
35 if (lsraddr
== NULL
|| source
== NULL
)
39 memset(a
, 0, sizeof(ldp_adj
));
40 MPLS_REFCNT_INIT(a
, 0);
41 MPLS_LIST_ELEM_INIT(a
, _global
);
42 MPLS_LIST_ELEM_INIT(a
, _session
);
43 MPLS_LIST_ELEM_INIT(a
, _entity
);
45 a
->index
= _ldp_adj_get_next_index();
47 /* these are operational values */
48 /* JLEU: where do I grab these values from */
50 /* these values are learned form the remote peer */
51 memcpy(&a
->remote_source_address
, source
, sizeof(mpls_inet_addr
));
52 memcpy(&a
->remote_lsr_address
, lsraddr
, sizeof(mpls_inet_addr
));
54 addr
.s_addr
= htonl(lsraddr
->u
.ipv4
);
55 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_PERIODIC
,
56 "Adj(%d) created for %s/",a
->index
, inet_ntoa(addr
));
57 addr
.s_addr
= htonl(source
->u
.ipv4
);
58 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_PERIODIC
,
59 "%s\n",inet_ntoa(addr
));
61 if (remote_transport_address
) {
62 memcpy(&a
->remote_transport_address
, remote_transport_address
,
63 sizeof(mpls_inet_addr
));
65 memset(&a
->remote_transport_address
, 0, sizeof(mpls_inet_addr
));
68 a
->remote_hellotime
= remote_hellotime
;
69 a
->remote_csn
= remote_csn
;
70 a
->state
= MPLS_OPER_DOWN
;
76 void ldp_adj_delete(ldp_adj
* a
)
78 LDP_PRINT(NULL
,"adj delete %p", a
);
79 MPLS_REFCNT_ASSERT(a
, 0);
83 mpls_return_enum
ldp_adj_startup(ldp_global
* g
, ldp_adj
* a
, int request
)
87 MPLS_ASSERT(a
&& (e
= a
->entity
));
88 /* with recent changes to when the session gets created I think this
89 * assert is not longer valid - jleu 2003-02-20
90 MPLS_ASSERT(!a->session);
92 MPLS_ASSERT(a
->state
!= LDP_NONE
);
94 LDP_ENTER(g
->user_data
, "ldp_adj_startup");
96 /* ldp-11 3.5.2. Hello Message */
97 if (e
->hellotime_timer
!= 0xFFFF) {
99 a
->hellotime_recv_timer
= mpls_timer_create(g
->timer_handle
, MPLS_UNIT_SEC
,
100 e
->hellotime_timer
, (void *)a
, g
, ldp_hello_timeout_callback
);
102 if (mpls_timer_handle_verify(g
->timer_handle
, a
->hellotime_recv_timer
) ==
104 MPLS_REFCNT_RELEASE(a
, ldp_adj_delete
);
105 goto ldp_adj_startup_error
;
109 if (request
&& mpls_timer_handle_verify(g
->timer_handle
,
110 e
->p
.peer
->hellotime_send_timer
) == MPLS_BOOL_FALSE
) {
111 /* request is ONLY specific with indirect adj */
112 ldp_hello_send(g
, e
);
115 a
->state
= MPLS_OPER_UP
;
117 if (e
->hellotime_timer
!= 0xFFFF) {
118 mpls_timer_start(g
->timer_handle
, a
->hellotime_recv_timer
,
122 LDP_EXIT(g
->user_data
, "ldp_adj_startup");
126 ldp_adj_startup_error
:
128 LDP_EXIT(g
->user_data
, "ldp_adj_startup: error");
133 #if 0 /* no one used this? */
134 mpls_return_enum
ldp_adj_restart(ldp_global
* g
, ldp_adj
* a
)
137 LDP_ENTER(g
->user_data
, "ldp_adj_restart");
139 if (a
->session
!= NULL
) {
140 ldp_session_shutdown(g
, a
->session
);
141 /* session_shutdown does this already ldp_adj_del_session(a); */
143 mpls_timer_stop(g
->timer_handle
, a
->hellotime_recv_timer
);
144 mpls_timer_start(g
->timer_handle
, a
->hellotime_recv_timer
, MPLS_TIMER_ONESHOT
);
146 LDP_EXIT(g
->user_data
, "ldp_adj_restart");
152 mpls_return_enum
ldp_adj_shutdown(ldp_global
* g
, ldp_adj
* a
)
156 MPLS_ASSERT(g
&& a
&& (e
= a
->entity
));
158 LDP_ENTER(g
->user_data
, "ldp_adj_shutdown");
163 ldp_session_shutdown(g
, a
->session
, MPLS_BOOL_TRUE
);
164 /* session_shutdown does ldp_adj_del_session(a); */
167 ldp_adj_recv_stop(g
, a
);
169 if (e
->entity_type
== LDP_INDIRECT
&&
170 e
->p
.peer
->target_role
== LDP_PASSIVE
) {
171 /* we started sending due to a targeted hello with "request"
172 * now that the adj is down we can stop
174 ldp_peer_send_stop(g
, e
->p
.peer
);
177 ldp_entity_del_adj(e
, a
);
178 if (a
->state
== MPLS_OPER_UP
) {
179 _ldp_global_del_adj(g
, a
);
182 LDP_EXIT(g
->user_data
, "ldp_adj_shutdown");
184 MPLS_REFCNT_RELEASE(a
, ldp_adj_delete
);
189 mpls_return_enum
ldp_adj_maintain_timer(ldp_global
* g
, ldp_adj
* a
)
191 mpls_return_enum retval
;
193 LDP_ENTER(g
->user_data
, "ldp_adj_maintain_timer");
195 mpls_timer_stop(g
->timer_handle
, a
->hellotime_recv_timer
);
197 mpls_timer_start(g
->timer_handle
, a
->hellotime_recv_timer
, MPLS_TIMER_ONESHOT
);
199 LDP_EXIT(g
->user_data
, "ldp_adj_maintain_timer");
204 mpls_return_enum
ldp_adj_recv_start(ldp_global
* g
, ldp_adj
* a
)
206 mpls_return_enum result
= MPLS_SUCCESS
;
208 LDP_ENTER(g
->user_data
, "ldp_adj_recv_start");
211 a
->hellotime_recv_timer
= mpls_timer_create(g
->timer_handle
, MPLS_UNIT_SEC
,
212 a
->entity
->hellotime_timer
, (void *)a
, g
, ldp_hello_timeout_callback
);
214 if (mpls_timer_handle_verify(g
->timer_handle
, a
->hellotime_recv_timer
) ==
216 MPLS_REFCNT_RELEASE(a
, ldp_adj_delete
);
217 result
= MPLS_FAILURE
;
220 LDP_EXIT(g
->user_data
, "ldp_adj_recv_start");
225 mpls_return_enum
ldp_adj_recv_stop(ldp_global
* g
, ldp_adj
* a
)
228 LDP_ENTER(g
->user_data
, "ldp_adj_recv_stop");
230 if (mpls_timer_handle_verify(g
->timer_handle
, a
->hellotime_recv_timer
) ==
232 mpls_timer_stop(g
->timer_handle
, a
->hellotime_recv_timer
);
233 mpls_timer_delete(g
->timer_handle
, a
->hellotime_recv_timer
);
234 a
->hellotime_recv_timer
= (mpls_timer_handle
) 0;
235 MPLS_REFCNT_RELEASE(a
, ldp_adj_delete
);
238 LDP_EXIT(g
->user_data
, "ldp_adj_recv_stop");
243 void _ldp_adj_add_entity(ldp_adj
* a
, ldp_entity
* e
)
250 void _ldp_adj_del_entity(ldp_adj
* a
, ldp_entity
*e
)
253 MPLS_REFCNT_RELEASE(e
, ldp_entity_delete
);
257 void ldp_adj_add_session(ldp_adj
* a
, ldp_session
* s
)
261 LDP_TRACE_LOG(g
->user_data
, MPLS_TRACE_STATE_ALL
, LDP_TRACE_FLAG_PERIODIC
,
262 "Adj(%d) bound to sesssion(%d)\n",a
->index
,s
->index
);
266 _ldp_session_add_adj(s
, a
);
269 void ldp_adj_del_session(ldp_adj
* a
, ldp_session
* s
)
272 _ldp_session_del_adj(s
, a
);
273 MPLS_REFCNT_RELEASE(s
, ldp_session_delete
);
277 uint32_t _ldp_adj_get_next_index()
279 uint32_t retval
= _ldp_adj_next_index
;
281 _ldp_adj_next_index
++;
282 if (retval
> _ldp_adj_next_index
) {
283 _ldp_adj_next_index
= 1;