Change inlabel outlabel/nexthop, and attr accounting. Specically
[mpls-ldp-portable.git] / ldp / ldp_adj.c
blob3b23ffa1f9853b27cd0e021e8831a08cf452dcf4
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_global.h"
14 #include "ldp_session.h"
15 #include "ldp_hello.h"
16 #include "ldp_global.h"
17 #include "ldp_entity.h"
18 #include "ldp_adj.h"
19 #include "ldp_peer.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));
33 struct in_addr addr;
35 if (lsraddr == NULL || source == NULL)
36 return NULL;
38 if (a) {
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));
64 } else {
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;
71 a->role = LDP_NONE;
73 return a;
76 void ldp_adj_delete(ldp_adj * a)
78 fprintf(stderr,"adj delete\n");
79 MPLS_REFCNT_ASSERT(a, 0);
80 mpls_free(a);
83 mpls_return_enum ldp_adj_startup(ldp_global * g, ldp_adj * a, int request)
85 ldp_entity *e;
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) {
98 MPLS_REFCNT_HOLD(a);
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) ==
103 MPLS_BOOL_FALSE) {
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,
119 MPLS_TIMER_ONESHOT);
122 LDP_EXIT(g->user_data, "ldp_adj_startup");
124 return MPLS_SUCCESS;
126 ldp_adj_startup_error:
128 LDP_EXIT(g->user_data, "ldp_adj_startup: error");
130 return MPLS_FAILURE;
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");
148 return MPLS_SUCCESS;
150 #endif
152 mpls_return_enum ldp_adj_shutdown(ldp_global * g, ldp_adj * a)
154 ldp_entity *e;
156 MPLS_ASSERT(g && a && (e = a->entity));
158 LDP_ENTER(g->user_data, "ldp_adj_shutdown");
160 MPLS_REFCNT_HOLD(a);
162 if (a->session) {
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);
186 return MPLS_SUCCESS;
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);
196 retval =
197 mpls_timer_start(g->timer_handle, a->hellotime_recv_timer, MPLS_TIMER_ONESHOT);
199 LDP_EXIT(g->user_data, "ldp_adj_maintain_timer");
201 return retval;
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");
210 MPLS_REFCNT_HOLD(a);
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) ==
215 MPLS_BOOL_FALSE) {
216 MPLS_REFCNT_RELEASE(a, ldp_adj_delete);
217 result = MPLS_FAILURE;
220 LDP_EXIT(g->user_data, "ldp_adj_recv_start");
222 return result;
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) ==
231 MPLS_BOOL_TRUE) {
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");
240 return MPLS_SUCCESS;
243 void _ldp_adj_add_entity(ldp_adj * a, ldp_entity * e)
245 MPLS_ASSERT(a && e);
246 MPLS_REFCNT_HOLD(e);
247 a->entity = e;
250 void _ldp_adj_del_entity(ldp_adj * a, ldp_entity *e)
252 MPLS_ASSERT(a && e);
253 MPLS_REFCNT_RELEASE(e, ldp_entity_delete);
254 a->entity = NULL;
257 void ldp_adj_add_session(ldp_adj * a, ldp_session * s)
259 MPLS_ASSERT(a && 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);
264 MPLS_REFCNT_HOLD(s);
265 a->session = s;
266 _ldp_session_add_adj(s, a);
269 void ldp_adj_del_session(ldp_adj * a, ldp_session * s)
271 MPLS_ASSERT(a && s);
272 _ldp_session_del_adj(s, a);
273 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
274 a->session = NULL;
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;
285 return retval;