an address can only be advertised by one session. Thus
[mpls-ldp-portable.git] / lsr / lsr_global.c
blob3dac8899e5a06ddebd92c97c5b7aee24a6f8f55a
2 /*
3 * Copyright (C) James R. Leu 2002
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 "lsr_struct.h"
11 #include "lsr_global.h"
12 #include "lsr_outsegment.h"
13 #include "lsr_insegment.h"
14 #include "lsr_xconnect.h"
15 #include "lsr_ftn.h"
16 #include "lsr_if.h"
18 #include "mpls_ifmgr_impl.h"
19 #include "mpls_mpls_impl.h"
20 #include "mpls_lock_impl.h"
21 #include "mpls_mm_impl.h"
22 #include "mpls_trace_impl.h"
24 lsr_global *lsr_global_create(mpls_instance_handle data)
26 lsr_global *g = (lsr_global *) mpls_malloc(sizeof(lsr_global));
28 if (g) {
29 memset(g, 0, sizeof(lsr_global));
31 LDP_ENTER(g->user_data, "lsr_global_create");
33 g->global_lock = mpls_lock_create("_lsr_global_lock_");
34 mpls_lock_get(g->global_lock);
36 MPLS_LIST_INIT(&g->outsegment, lsr_outsegment);
37 MPLS_LIST_INIT(&g->insegment, lsr_insegment);
38 MPLS_LIST_INIT(&g->xconnect, lsr_xconnect);
39 MPLS_LIST_INIT(&g->ftn, lsr_ftn);
40 MPLS_LIST_INIT(&g->iff, lsr_if);
42 g->admin_state = MPLS_ADMIN_DISABLE;
43 g->user_data = data;
45 mpls_lock_release(g->global_lock);
47 LDP_EXIT(g->user_data, "lsr_global_create");
50 return g;
53 mpls_return_enum lsr_global_startup(lsr_global * g)
55 MPLS_ASSERT(g != NULL);
57 LDP_ENTER(g->user_data, "lsr_global_startup");
59 g->ifmgr_handle = mpls_ifmgr_open(g->user_data, g);
60 if (mpls_ifmgr_handle_verify(g->ifmgr_handle) == MPLS_BOOL_FALSE) {
61 goto lsr_global_startup_cleanup;
64 g->mpls_handle = mpls_mpls_open(g->user_data);
65 if (mpls_mpls_handle_verify(g->mpls_handle) == MPLS_BOOL_FALSE) {
66 goto lsr_global_startup_cleanup;
69 g->admin_state = MPLS_ADMIN_ENABLE;
71 LDP_EXIT(g->user_data, "lsr_global_startup");
72 return MPLS_SUCCESS;
74 lsr_global_startup_cleanup:
75 lsr_global_shutdown(g);
77 LDP_EXIT(g->user_data, "lsr_global_startup-error");
79 return MPLS_FAILURE;
82 mpls_return_enum lsr_global_shutdown(lsr_global * g)
84 MPLS_ASSERT(g);
86 LDP_ENTER(g->user_data, "lsr_global_shutdown");
88 g->admin_state = MPLS_ADMIN_DISABLE;
90 mpls_lock_release(g->global_lock);
91 mpls_lock_get(g->global_lock);
93 mpls_ifmgr_close(g->ifmgr_handle);
94 mpls_mpls_close(g->mpls_handle);
96 LDP_EXIT(g->user_data, "lsr_global_shutdown");
98 return MPLS_SUCCESS;
101 mpls_return_enum lsr_global_delete(lsr_global * g)
103 if (g) {
104 mpls_lock_delete(g->global_lock);
105 LDP_PRINT(g->user_data, "global delete\n");
106 mpls_free(g);
108 return MPLS_SUCCESS;
111 /* struct if */
113 mpls_return_enum _lsr_global_add_if(lsr_global * g, lsr_if * i)
115 lsr_if *ip = NULL;
117 if (g && i) {
118 MPLS_REFCNT_HOLD(i);
119 ip = MPLS_LIST_HEAD(&g->iff);
120 while (ip != NULL) {
121 if (ip->index > i->index) {
122 MPLS_LIST_INSERT_BEFORE(&g->iff, ip, i, _global);
123 return MPLS_SUCCESS;
125 ip = MPLS_LIST_NEXT(&g->iff, ip, _global);
127 MPLS_LIST_ADD_TAIL(&g->iff, i, _global, lsr_if);
128 return MPLS_SUCCESS;
130 return MPLS_FAILURE;
133 mpls_return_enum _lsr_global_del_if(lsr_global * g, lsr_if * i)
135 if (g && i) {
136 MPLS_LIST_REMOVE(&g->iff, i, _global);
137 MPLS_REFCNT_RELEASE(i, lsr_if_delete);
138 return MPLS_SUCCESS;
140 return MPLS_FAILURE;
143 mpls_return_enum lsr_global_find_if_index(lsr_global * g, uint32_t index,
144 lsr_if ** iff)
146 lsr_if *i = NULL;
148 if (g && index > 0) {
150 /* because we sort our inserts by index, this lets us know
151 if we've "walked" past the end of the list */
153 i = MPLS_LIST_TAIL(&g->iff);
154 if (i == NULL || i->index < index) {
155 *iff = NULL;
156 return MPLS_END_OF_LIST;
159 i = MPLS_LIST_HEAD(&g->iff);
160 while (i != NULL) {
161 if (i->index == index) {
162 *iff = i;
163 return MPLS_SUCCESS;
165 i = MPLS_LIST_NEXT(&g->iff, i, _global);
168 *iff = NULL;
169 return MPLS_FAILURE;
172 lsr_if * lsr_global_find_if_handle(lsr_global * g, mpls_if_handle ifhandle)
174 lsr_if *i = NULL;
176 if (g && mpls_if_handle_verify(g->ifmgr_handle, ifhandle) == MPLS_BOOL_TRUE) {
177 i = MPLS_LIST_HEAD(&g->iff);
178 while (i != NULL) {
179 if (!mpls_if_handle_compare(i->handle, ifhandle)) {
180 return i;
182 i = MPLS_LIST_NEXT(&g->iff, i, _global);
185 return NULL;
188 /* struct outsegment */
190 mpls_return_enum _lsr_global_add_outsegment(lsr_global * g, lsr_outsegment * o)
192 lsr_outsegment *op = NULL;
194 if (g && o) {
195 MPLS_REFCNT_HOLD(o);
196 op = MPLS_LIST_HEAD(&g->outsegment);
197 while (op != NULL) {
198 if (op->index > o->index) {
199 MPLS_LIST_INSERT_BEFORE(&g->outsegment, op, o, _global);
200 return MPLS_SUCCESS;
202 op = MPLS_LIST_NEXT(&g->outsegment, op, _global);
204 MPLS_LIST_ADD_TAIL(&g->outsegment, o, _global, lsr_outsegment);
205 return MPLS_SUCCESS;
207 return MPLS_FAILURE;
210 mpls_return_enum _lsr_global_del_outsegment(lsr_global * g, lsr_outsegment * o)
212 if (g && o) {
213 MPLS_LIST_REMOVE(&g->outsegment, o, _global);
214 MPLS_REFCNT_RELEASE(o, lsr_outsegment_delete);
215 return MPLS_SUCCESS;
217 return MPLS_FAILURE;
220 mpls_return_enum lsr_global_find_outsegment_index(lsr_global * g,
221 uint32_t index, lsr_outsegment ** outsegment)
223 lsr_outsegment *o = NULL;
225 if (g && index > 0) {
227 /* because we sort our inserts by index, this lets us know
228 if we've "walked" past the end of the list */
230 o = MPLS_LIST_TAIL(&g->outsegment);
231 if (o == NULL || o->index < index) {
232 *outsegment = NULL;
233 return MPLS_END_OF_LIST;
236 o = MPLS_LIST_HEAD(&g->outsegment);
237 while (o != NULL) {
238 if (o->index == index) {
239 *outsegment = o;
240 return MPLS_SUCCESS;
242 o = MPLS_LIST_NEXT(&g->outsegment, o, _global);
245 *outsegment = NULL;
246 return MPLS_FAILURE;
249 /* struct insegment */
251 mpls_return_enum _lsr_global_add_insegment(lsr_global * g, lsr_insegment * i)
253 lsr_insegment *ip = NULL;
255 if (g && i) {
256 MPLS_REFCNT_HOLD(i);
257 ip = MPLS_LIST_HEAD(&g->insegment);
258 while (ip != NULL) {
259 if (ip->index > i->index) {
260 MPLS_LIST_INSERT_BEFORE(&g->insegment, ip, i, _global);
261 return MPLS_SUCCESS;
263 ip = MPLS_LIST_NEXT(&g->insegment, ip, _global);
265 MPLS_LIST_ADD_TAIL(&g->insegment, i, _global, lsr_insegment);
266 return MPLS_SUCCESS;
268 return MPLS_FAILURE;
271 mpls_return_enum _lsr_global_del_insegment(lsr_global * g, lsr_insegment * i)
273 if (g && i) {
274 MPLS_LIST_REMOVE(&g->insegment, i, _global);
275 MPLS_REFCNT_RELEASE(i, lsr_insegment_delete);
276 return MPLS_SUCCESS;
278 return MPLS_FAILURE;
281 mpls_return_enum lsr_global_find_insegment_index(lsr_global * g,
282 uint32_t index, lsr_insegment ** insegment)
284 lsr_insegment *i = NULL;
286 if (g && index > 0) {
288 /* because we sort our inserts by index, this lets us know
289 if we've "walked" past the end of the list */
291 i = MPLS_LIST_TAIL(&g->insegment);
292 if (i == NULL || i->index < index) {
293 *insegment = NULL;
294 return MPLS_END_OF_LIST;
297 i = MPLS_LIST_HEAD(&g->insegment);
298 while (i != NULL) {
299 if (i->index == index) {
300 *insegment = i;
301 return MPLS_SUCCESS;
303 i = MPLS_LIST_NEXT(&g->insegment, i, _global);
306 *insegment = NULL;
307 return MPLS_FAILURE;
310 /* struct xconnect */
312 mpls_return_enum _lsr_global_add_xconnect(lsr_global * g, lsr_xconnect * x)
314 lsr_xconnect *xp = NULL;
316 if (g && x) {
317 MPLS_REFCNT_HOLD(x);
318 xp = MPLS_LIST_HEAD(&g->xconnect);
319 while (xp != NULL) {
320 if (xp->index > x->index) {
321 MPLS_LIST_INSERT_BEFORE(&g->xconnect, xp, x, _global);
322 return MPLS_SUCCESS;
324 xp = MPLS_LIST_NEXT(&g->xconnect, xp, _global);
326 MPLS_LIST_ADD_TAIL(&g->xconnect, x, _global, lsr_xconnect);
327 return MPLS_SUCCESS;
329 return MPLS_FAILURE;
332 mpls_return_enum _lsr_global_del_xconnect(lsr_global * g, lsr_xconnect * x)
334 if (g && x) {
335 MPLS_LIST_REMOVE(&g->xconnect, x, _global);
336 MPLS_REFCNT_RELEASE(x, lsr_xconnect_delete);
337 return MPLS_SUCCESS;
339 return MPLS_FAILURE;
342 mpls_return_enum lsr_global_find_xconnect_index(lsr_global * g,
343 uint32_t index, lsr_xconnect ** xconnect)
345 lsr_xconnect *x = NULL;
347 if (g && index > 0) {
349 /* because we sort our inserts by index, this lets us know
350 if we've "walked" past the end of the list */
352 x = MPLS_LIST_TAIL(&g->xconnect);
353 if (x == NULL || x->index < index) {
354 *xconnect = NULL;
355 return MPLS_END_OF_LIST;
358 x = MPLS_LIST_HEAD(&g->xconnect);
359 while (x != NULL) {
360 if (x->index == index) {
361 *xconnect = x;
362 return MPLS_SUCCESS;
364 x = MPLS_LIST_NEXT(&g->xconnect, x, _global);
367 *xconnect = NULL;
368 return MPLS_FAILURE;
371 mpls_return_enum lsr_global_find_xconnect_index2(lsr_global * g,
372 uint32_t in, uint32_t out, lsr_xconnect ** xconnect)
374 lsr_insegment *iseg = NULL;
375 lsr_xconnect *x = NULL;
377 if (g && in > 0 && out > 0) {
379 if (lsr_global_find_insegment_index(g,in,&iseg) != MPLS_SUCCESS) {
380 return MPLS_FAILURE;
383 x = MPLS_LIST_HEAD(&iseg->xconnect_root);
384 while (x != NULL) {
385 if (x->outsegment && x->outsegment->index == out) {
386 *xconnect = x;
387 return MPLS_SUCCESS;
389 x = MPLS_LIST_NEXT(&iseg->xconnect_root, x, _insegment);
392 *xconnect = NULL;
393 return MPLS_FAILURE;
396 /* struct ftn */
398 void _lsr_global_add_ftn(lsr_global * g, lsr_ftn * f)
400 lsr_ftn *fp = NULL;
402 MPLS_ASSERT(g && f);
404 MPLS_REFCNT_HOLD(f);
405 fp = MPLS_LIST_HEAD(&g->ftn);
406 while (fp != NULL) {
407 if (fp->index > f->index) {
408 MPLS_LIST_INSERT_BEFORE(&g->ftn, fp, f, _global);
409 return;
411 fp = MPLS_LIST_NEXT(&g->ftn, fp, _global);
413 MPLS_LIST_ADD_TAIL(&g->ftn, f, _global, lsr_ftn);
416 void _lsr_global_del_ftn(lsr_global * g, lsr_ftn * f)
418 MPLS_ASSERT(g && f);
419 MPLS_LIST_REMOVE(&g->ftn, f, _global);
420 MPLS_REFCNT_RELEASE(f, lsr_ftn_delete);
423 mpls_return_enum lsr_global_find_ftn_index(lsr_global * g,
424 uint32_t index, lsr_ftn ** ftn)
426 lsr_ftn *f = NULL;
428 MPLS_ASSERT(g && index > 0);
430 /* because we sort our inserts by index, this lets us know
431 if we've "walked" past the end of the list */
433 f = MPLS_LIST_TAIL(&g->ftn);
434 if (f == NULL || f->index < index) {
435 *ftn = NULL;
436 return MPLS_END_OF_LIST;
439 f = MPLS_LIST_HEAD(&g->ftn);
440 while (f != NULL) {
441 if (f->index == index) {
442 *ftn = f;
443 return MPLS_SUCCESS;
445 f = MPLS_LIST_NEXT(&g->ftn, f, _global);
447 *ftn = NULL;
448 return MPLS_FAILURE;
451 mpls_return_enum lsr_global_find_ftn_index2(lsr_global * g,
452 lsr_ftn * f, lsr_ftn ** ftn)
454 lsr_ftn *fp = NULL;
456 if (g && f) {
457 fp = MPLS_LIST_HEAD(&g->ftn);
458 while (fp != NULL) {
459 if (fp->outsegment->index == f->outsegment_index) {
460 if (fp->fec.type == f->fec.type) {
461 switch(fp->fec.type) {
462 case MPLS_FEC_PREFIX:
463 if (fp->fec.u.prefix.network.u.ipv4 == f->fec.u.prefix.network.u.ipv4 &&
464 fp->fec.u.prefix.length == f->fec.u.prefix.length) {
465 *ftn = fp;
466 return MPLS_SUCCESS;
468 break;
469 case MPLS_FEC_HOST:
470 if (fp->fec.u.host.u.ipv4 == f->fec.u.host.u.ipv4) {
471 *ftn = fp;
472 return MPLS_SUCCESS;
474 break;
475 case MPLS_FEC_L2CC:
476 if (fp->fec.u.l2cc.connection_id == f->fec.u.l2cc.connection_id &&
477 fp->fec.u.l2cc.group_id == f->fec.u.l2cc.group_id &&
478 fp->fec.u.l2cc.type == f->fec.u.l2cc.type) {
479 *ftn = fp;
480 return MPLS_SUCCESS;
482 break;
483 default:
484 MPLS_ASSERT(0);
488 fp = MPLS_LIST_NEXT(&g->ftn, fp, _global);
491 *ftn = NULL;
492 return MPLS_FAILURE;