Add comment to ldp/ldp_global.c stating that we need to do some
[mpls-ldp-portable.git] / ldp / ldp_global.c
blob05156e9a45af23001715e424512341e667b41750
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 <netinet/in.h>
12 #include "ldp_struct.h"
13 #include "ldp_inet_addr.h"
14 #include "ldp_session.h"
15 #include "ldp_entity.h"
16 #include "ldp_global.h"
17 #include "ldp_nexthop.h"
18 #include "ldp_outlabel.h"
19 #include "ldp_inlabel.h"
20 #include "ldp_hello.h"
21 #include "ldp_peer.h"
22 #include "ldp_attr.h"
23 #include "ldp_addr.h"
24 #include "ldp_adj.h"
25 #include "ldp_fec.h"
26 #include "ldp_if.h"
27 #include "ldp_label_mapping.h"
28 #include "ldp_tunnel.h"
29 #include "ldp_resource.h"
30 #include "ldp_hop_list.h"
32 #include "mpls_compare.h"
34 #include "mpls_socket_impl.h"
35 #include "mpls_timer_impl.h"
36 #include "mpls_ifmgr_impl.h"
37 #include "mpls_tree_impl.h"
38 #include "mpls_lock_impl.h"
39 #include "mpls_fib_impl.h"
40 #include "mpls_policy_impl.h"
41 #include "mpls_mm_impl.h"
42 #include "mpls_trace_impl.h"
44 #if MPLS_USE_LSR
45 #include "lsr_cfg.h"
46 #else
47 #include "mpls_mpls_impl.h"
48 #endif
50 ldp_global *ldp_global_create(mpls_instance_handle data)
52 ldp_global *g = (ldp_global *) mpls_malloc(sizeof(ldp_global));
54 if (g) {
55 memset(g, 0, sizeof(ldp_global));
57 LDP_ENTER(g->user_data, "ldp_global_create");
59 g->global_lock = mpls_lock_create("_ldp_global_lock_");
60 mpls_lock_get(g->global_lock);
62 MPLS_LIST_INIT(&g->hop_list, ldp_hop_list);
63 MPLS_LIST_INIT(&g->outlabel, ldp_outlabel);
64 MPLS_LIST_INIT(&g->resource, ldp_resource);
65 MPLS_LIST_INIT(&g->inlabel, ldp_inlabel);
66 MPLS_LIST_INIT(&g->session, ldp_session);
67 MPLS_LIST_INIT(&g->nexthop, ldp_nexthop);
68 MPLS_LIST_INIT(&g->tunnel, ldp_tunnel);
69 MPLS_LIST_INIT(&g->entity, ldp_entity);
70 MPLS_LIST_INIT(&g->addr, ldp_addr);
71 MPLS_LIST_INIT(&g->attr, ldp_attr);
72 MPLS_LIST_INIT(&g->peer, ldp_peer);
73 MPLS_LIST_INIT(&g->fec, ldp_fec);
74 MPLS_LIST_INIT(&g->adj, ldp_adj);
75 MPLS_LIST_INIT(&g->iff, ldp_if);
77 g->message_identifier = 1;
78 g->configuration_sequence_number = 1;
79 g->lsp_control_mode = LDP_GLOBAL_DEF_CONTROL_MODE;
80 g->label_retention_mode = LDP_GLOBAL_DEF_RETENTION_MODE;
81 g->lsp_repair_mode = LDP_GLOBAL_DEF_REPAIR_MODE;
82 g->propagate_release = LDP_GLOBAL_DEF_PROPOGATE_RELEASE;
83 g->label_merge = LDP_GLOBAL_DEF_LABEL_MERGE;
84 g->loop_detection_mode = LDP_GLOBAL_DEF_LOOP_DETECTION_MODE;
85 g->ttl_less_domain = LDP_GLOBAL_DEF_TTLLESS_DOMAIN;
86 g->local_tcp_port = LDP_GLOBAL_DEF_LOCAL_TCP_PORT;
87 g->local_udp_port = LDP_GLOBAL_DEF_LOCAL_UDP_PORT;
88 g->send_address_messages = LDP_GLOBAL_DEF_SEND_ADDR_MSG;
89 g->backoff_step = LDP_GLOBAL_DEF_BACKOFF_STEP;
90 g->send_lsrid_mapping = LDP_GLOBAL_DEF_SEND_LSRID_MAPPING;
91 g->no_route_to_peer_time = LDP_GLOBAL_DEF_NO_ROUTE_RETRY_TIME;
93 g->keepalive_timer = LDP_ENTITY_DEF_KEEPALIVE_TIMER;
94 g->keepalive_interval = LDP_ENTITY_DEF_KEEPALIVE_INTERVAL;
95 g->hellotime_timer = LDP_ENTITY_DEF_HELLOTIME_TIMER;
96 g->hellotime_interval = LDP_ENTITY_DEF_HELLOTIME_INTERVAL;
98 g->admin_state = MPLS_ADMIN_DISABLE;
99 g->user_data = data;
101 g->addr_tree = mpls_tree_create(32);
102 g->fec_tree = mpls_tree_create(32);
104 mpls_lock_release(g->global_lock);
106 LDP_EXIT(g->user_data, "ldp_global_create");
109 return g;
112 mpls_return_enum ldp_global_startup(ldp_global * g)
114 ldp_entity *e = NULL;
115 mpls_dest dest;
117 MPLS_ASSERT(g != NULL);
119 LDP_ENTER(g->user_data, "ldp_global_startup");
121 if (g->lsr_identifier.type == MPLS_FAMILY_NONE) {
122 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_ERROR,
123 "ldp_global_startup: invalid LSRID\n");
124 goto ldp_global_startup_cleanup;
127 g->timer_handle = mpls_timer_open(g->user_data);
128 if (mpls_timer_mgr_handle_verify(g->timer_handle) == MPLS_BOOL_FALSE) {
129 goto ldp_global_startup_cleanup;
132 g->socket_handle = mpls_socket_mgr_open(g->user_data);
133 if (mpls_socket_mgr_handle_verify(g->socket_handle) == MPLS_BOOL_FALSE) {
134 goto ldp_global_startup_cleanup;
137 g->ifmgr_handle = mpls_ifmgr_open(g->user_data, g);
138 if (mpls_ifmgr_handle_verify(g->ifmgr_handle) == MPLS_BOOL_FALSE) {
139 goto ldp_global_startup_cleanup;
142 g->fib_handle = mpls_fib_open(g->user_data, g);
143 if (mpls_fib_handle_verify(g->fib_handle) == MPLS_BOOL_FALSE) {
144 goto ldp_global_startup_cleanup;
147 #if MPLS_USE_LSR
148 if (!g->lsr_handle) {
149 goto ldp_global_startup_cleanup;
151 #else
152 g->mpls_handle = mpls_mpls_open(g->user_data);
153 if (mpls_mpls_handle_verify(g->mpls_handle) == MPLS_BOOL_FALSE) {
154 goto ldp_global_startup_cleanup;
156 #endif
158 g->hello_socket = mpls_socket_create_udp(g->socket_handle);
159 if (mpls_socket_handle_verify(g->socket_handle, g->hello_socket) == MPLS_BOOL_FALSE) {
160 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
161 "ldp_global_startup: error creating UDP socket\n");
162 goto ldp_global_startup_cleanup;
165 dest.addr.type = MPLS_FAMILY_IPV4;
166 dest.port = g->local_udp_port;
167 dest.addr.u.ipv4 = INADDR_ANY;
168 // dest.addr.u.ipv4 = INADDR_ALLRTRS_GROUP;
170 if (mpls_socket_bind(g->socket_handle, g->hello_socket, &dest) == MPLS_FAILURE) {
171 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
172 "ldp_global_startup: error binding UDP socket\n");
173 goto ldp_global_startup_cleanup;
176 if (mpls_socket_options(g->socket_handle, g->hello_socket,
177 MPLS_SOCKOP_NONBLOCK | MPLS_SOCKOP_REUSE) == MPLS_FAILURE) {
178 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
179 "ldp_global_startup: error setting UDP socket options\n");
180 goto ldp_global_startup_cleanup;
182 if (mpls_socket_multicast_options(g->socket_handle, g->hello_socket, 1, 0) ==
183 MPLS_FAILURE) {
184 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
185 "ldp_global_startup: error setting UDP socket multicast options\n");
186 goto ldp_global_startup_cleanup;
188 mpls_socket_readlist_add(g->socket_handle, g->hello_socket, 0, MPLS_SOCKET_UDP_DATA);
190 g->listen_socket = mpls_socket_create_tcp(g->socket_handle);
191 if (mpls_socket_handle_verify(g->socket_handle, g->listen_socket) == MPLS_BOOL_FALSE) {
192 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
193 "ldp_global_startup: error creating TCP socket\n");
194 goto ldp_global_startup_cleanup;
196 if (mpls_socket_options(g->socket_handle, g->listen_socket,
197 MPLS_SOCKOP_NONBLOCK | MPLS_SOCKOP_REUSE) == MPLS_FAILURE) {
198 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
199 "ldp_global_startup: error setting TCP socket options\n");
200 goto ldp_global_startup_cleanup;
203 dest.addr.type = MPLS_FAMILY_IPV4;
204 dest.port = g->local_tcp_port;
205 dest.addr.u.ipv4 = INADDR_ANY;
207 if (mpls_socket_bind(g->socket_handle, g->listen_socket, &dest) == MPLS_FAILURE) {
208 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
209 "ldp_global_startup: error binding TCP socket\n");
210 goto ldp_global_startup_cleanup;
213 if (mpls_socket_tcp_listen(g->socket_handle, g->listen_socket, 15) ==
214 MPLS_FAILURE) {
215 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
216 "ldp_global_startup: error setting listen buffer for TCP socket\n");
217 goto ldp_global_startup_cleanup;
220 mpls_socket_readlist_add(g->socket_handle, g->listen_socket, 0,
221 MPLS_SOCKET_TCP_LISTEN);
223 g->admin_state = MPLS_ADMIN_ENABLE;
225 e = MPLS_LIST_HEAD(&g->entity);
226 while (e != NULL) {
227 ldp_entity_startup(g, e);
228 e = MPLS_LIST_NEXT(&g->entity, e, _global);
231 LDP_EXIT(g->user_data, "ldp_global_startup");
232 return MPLS_SUCCESS;
234 ldp_global_startup_cleanup:
235 ldp_global_shutdown(g);
236 mpls_socket_close(g->socket_handle, g->hello_socket);
237 mpls_socket_close(g->socket_handle, g->listen_socket);
238 g->hello_socket = 0;
239 g->listen_socket = 0;
241 LDP_EXIT(g->user_data, "ldp_global_startup-error");
243 return MPLS_FAILURE;
246 mpls_return_enum ldp_global_shutdown(ldp_global * g)
248 ldp_entity *e = NULL;
249 ldp_nexthop *n;
250 ldp_fec *f;
251 ldp_addr *a;
252 ldp_if *i;
254 MPLS_ASSERT(g);
256 LDP_ENTER(g->user_data, "ldp_global_shutdown");
258 e = MPLS_LIST_HEAD(&g->entity);
259 while (e != NULL) {
260 ldp_entity_shutdown(g, e, 1);
261 e = MPLS_LIST_NEXT(&g->entity, e, _global);
264 g->admin_state = MPLS_ADMIN_DISABLE;
266 mpls_socket_readlist_del(g->socket_handle, g->hello_socket);
267 mpls_socket_close(g->socket_handle, g->hello_socket);
269 mpls_socket_readlist_del(g->socket_handle, g->listen_socket);
270 mpls_socket_close(g->socket_handle, g->listen_socket);
272 mpls_lock_release(g->global_lock);
273 mpls_timer_close(g->timer_handle);
274 mpls_lock_get(g->global_lock);
276 mpls_socket_mgr_close(g->socket_handle);
277 mpls_ifmgr_close(g->ifmgr_handle);
278 mpls_fib_close(g->fib_handle);
280 #if MPLS_USE_LSR
281 #else
282 mpls_mpls_close(g->mpls_handle);
283 #endif
285 LDP_EXIT(g->user_data, "ldp_global_shutdown");
287 return MPLS_SUCCESS;
290 mpls_return_enum ldp_global_delete(ldp_global * g)
292 if (g) {
293 /* need to properly purge FECs/nexthops/interfaces/addresses */
294 mpls_tree_delete(g->addr_tree);
295 mpls_tree_delete(g->fec_tree);
297 mpls_lock_delete(g->global_lock);
298 LDP_PRINT(g->user_data, "global delete\n");
299 mpls_free(g);
301 return MPLS_SUCCESS;
304 void _ldp_global_add_attr(ldp_global * g, ldp_attr * a)
306 ldp_attr *ap = NULL;
308 MPLS_ASSERT(g && a);
309 MPLS_REFCNT_HOLD(a);
310 ap = MPLS_LIST_HEAD(&g->attr);
311 while (ap != NULL) {
312 if (ap->index > a->index) {
313 MPLS_LIST_INSERT_BEFORE(&g->attr, ap, a, _global);
314 return;
316 ap = MPLS_LIST_NEXT(&g->attr, ap, _global);
318 MPLS_LIST_ADD_TAIL(&g->attr, a, _global, ldp_attr);
321 void _ldp_global_del_attr(ldp_global * g, ldp_attr * a)
323 MPLS_ASSERT(g && a);
324 MPLS_LIST_REMOVE(&g->attr, a, _global);
325 MPLS_REFCNT_RELEASE(a, ldp_attr_delete);
328 void _ldp_global_add_peer(ldp_global * g, ldp_peer * p)
330 ldp_peer *pp = NULL;
332 MPLS_ASSERT(g && p);
333 MPLS_REFCNT_HOLD(p);
334 pp = MPLS_LIST_HEAD(&g->peer);
335 while (pp != NULL) {
336 if (pp->index > p->index) {
337 MPLS_LIST_INSERT_BEFORE(&g->peer, pp, p, _global);
338 return;
340 pp = MPLS_LIST_NEXT(&g->peer, pp, _global);
342 MPLS_LIST_ADD_TAIL(&g->peer, p, _global, ldp_peer);
345 void _ldp_global_del_peer(ldp_global * g, ldp_peer * p)
347 MPLS_ASSERT(g && p);
348 MPLS_LIST_REMOVE(&g->peer, p, _global);
349 MPLS_REFCNT_RELEASE(p, ldp_peer_delete);
353 * _ldp_global_add_if/del_if and _ldp_global_add_addr/del_addr are
354 * not the same as the rest of the global_add/del functions. They
355 * do not hold refcnts, they are used as part of the create and delete
356 * process of these structures
359 void _ldp_global_add_if(ldp_global * g, ldp_if * i)
361 ldp_if *ip = NULL;
363 MPLS_ASSERT(g && i);
364 ip = MPLS_LIST_HEAD(&g->iff);
365 while (ip != NULL) {
366 if (ip->index > i->index) {
367 MPLS_LIST_INSERT_BEFORE(&g->iff, ip, i, _global);
368 return;
370 ip = MPLS_LIST_NEXT(&g->iff, ip, _global);
372 MPLS_LIST_ADD_TAIL(&g->iff, i, _global, ldp_if);
375 void _ldp_global_del_if(ldp_global * g, ldp_if * i)
377 MPLS_ASSERT(g && i);
378 MPLS_LIST_REMOVE(&g->iff, i, _global);
381 void _ldp_global_add_addr(ldp_global * g, ldp_addr * a)
383 ldp_addr *ap = NULL;
385 MPLS_ASSERT(g && a);
386 ap = MPLS_LIST_HEAD(&g->addr);
387 while (ap != NULL) {
388 if (ap->index > a->index) {
389 MPLS_LIST_INSERT_BEFORE(&g->addr, ap, a, _global);
390 return;
392 ap = MPLS_LIST_NEXT(&g->addr, ap, _global);
394 MPLS_LIST_ADD_TAIL(&g->addr, a, _global, ldp_addr);
397 void _ldp_global_del_addr(ldp_global * g, ldp_addr * a)
399 MPLS_ASSERT(g && a);
400 MPLS_LIST_REMOVE(&g->addr, a, _global);
403 void _ldp_global_add_adj(ldp_global * g, ldp_adj * a)
405 ldp_adj *ap = NULL;
407 MPLS_ASSERT(g && a);
408 MPLS_REFCNT_HOLD(a);
409 ap = MPLS_LIST_HEAD(&g->adj);
410 while (ap != NULL) {
411 if (ap->index > a->index) {
412 MPLS_LIST_INSERT_BEFORE(&g->adj, ap, a, _global);
413 return;
415 ap = MPLS_LIST_NEXT(&g->adj, ap, _global);
417 MPLS_LIST_ADD_TAIL(&g->adj, a, _global, ldp_adj);
420 void _ldp_global_del_adj(ldp_global * g, ldp_adj * a)
422 MPLS_ASSERT(g && a);
423 MPLS_LIST_REMOVE(&g->adj, a, _global);
424 MPLS_REFCNT_RELEASE(a, ldp_adj_delete);
427 void _ldp_global_add_entity(ldp_global * g, ldp_entity * e)
429 ldp_entity *ep = NULL;
431 MPLS_ASSERT(g && e);
432 MPLS_REFCNT_HOLD(e);
433 ep = MPLS_LIST_HEAD(&g->entity);
434 while (ep != NULL) {
435 if (ep->index > e->index) {
436 MPLS_LIST_INSERT_BEFORE(&g->entity, ep, e, _global);
437 return;
439 ep = MPLS_LIST_NEXT(&g->entity, ep, _global);
441 MPLS_LIST_ADD_TAIL(&g->entity, e, _global, ldp_entity);
444 void _ldp_global_del_entity(ldp_global * g, ldp_entity * e)
446 MPLS_ASSERT(g && e);
447 MPLS_LIST_REMOVE(&g->entity, e, _global);
448 MPLS_REFCNT_RELEASE(e, ldp_entity_delete);
451 void _ldp_global_add_session(ldp_global * g, ldp_session * s)
453 ldp_session *sp = NULL;
455 MPLS_ASSERT(g && s);
456 MPLS_REFCNT_HOLD(s);
457 s->on_global = MPLS_BOOL_TRUE;
458 sp = MPLS_LIST_HEAD(&g->session);
459 while (sp != NULL) {
460 if (sp->index > s->index) {
461 MPLS_LIST_INSERT_BEFORE(&g->session, sp, s, _global);
462 return;
464 sp = MPLS_LIST_NEXT(&g->session, sp, _global);
466 MPLS_LIST_ADD_TAIL(&g->session, s, _global, ldp_session);
469 void _ldp_global_del_session(ldp_global * g, ldp_session * s)
471 MPLS_ASSERT(g && s);
472 MPLS_ASSERT(s->on_global == MPLS_BOOL_TRUE);
473 MPLS_LIST_REMOVE(&g->session, s, _global);
474 s->on_global = MPLS_BOOL_FALSE;
475 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
478 mpls_return_enum _ldp_global_add_inlabel(ldp_global * g, ldp_inlabel * i)
480 ldp_inlabel *ip = NULL;
481 mpls_return_enum result;
483 MPLS_ASSERT(g && i);
485 #if MPLS_USE_LSR
487 lsr_insegment iseg;
488 memcpy(&iseg.info,&i->info,sizeof(mpls_insegment));
489 result = lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_ADD|
490 LSR_INSEGMENT_CFG_NPOP|LSR_INSEGMENT_CFG_FAMILY|
491 LSR_INSEGMENT_CFG_LABELSPACE|LSR_INSEGMENT_CFG_LABEL|
492 LSR_INSEGMENT_CFG_OWNER);
493 memcpy(&i->info, &iseg.info, sizeof(mpls_insegment));
494 i->info.handle = iseg.index;
496 #else
497 result = mpls_mpls_insegment_add(g->mpls_handle, &i->info);
498 #endif
499 if (result != MPLS_SUCCESS) {
500 return result;
503 MPLS_REFCNT_HOLD(i);
504 ip = MPLS_LIST_HEAD(&g->inlabel);
505 while (ip != NULL) {
506 if (ip->index > i->index) {
507 MPLS_LIST_INSERT_BEFORE(&g->inlabel, ip, i, _global);
508 return MPLS_SUCCESS;
510 ip = MPLS_LIST_NEXT(&g->inlabel, ip, _global);
512 MPLS_LIST_ADD_TAIL(&g->inlabel, i, _global, ldp_inlabel);
513 return MPLS_SUCCESS;
516 mpls_return_enum _ldp_global_del_inlabel(ldp_global * g, ldp_inlabel * i)
518 MPLS_ASSERT(g && i);
519 MPLS_ASSERT(i->reuse_count == 0);
520 #if MPLS_USE_LSR
522 lsr_insegment iseg;
523 iseg.index = i->info.handle;
524 lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_DEL);
526 #else
527 mpls_mpls_insegment_del(g->mpls_handle, &i->info);
528 #endif
529 MPLS_LIST_REMOVE(&g->inlabel, i, _global);
530 MPLS_REFCNT_RELEASE(i, ldp_inlabel_delete);
531 return MPLS_SUCCESS;
534 mpls_return_enum _ldp_global_add_outlabel(ldp_global * g, ldp_outlabel * o)
536 ldp_outlabel *op = NULL;
537 mpls_return_enum result;
539 MPLS_ASSERT(g && o);
540 #if MPLS_USE_LSR
542 lsr_outsegment oseg;
543 memcpy(&oseg.info, &o->info, sizeof(mpls_outsegment));
544 result = lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_ADD|
545 LSR_OUTSEGMENT_CFG_PUSH_LABEL|LSR_OUTSEGMENT_CFG_OWNER|
546 LSR_OUTSEGMENT_CFG_INTERFACE|LSR_OUTSEGMENT_CFG_LABEL|
547 LSR_OUTSEGMENT_CFG_NEXTHOP);
548 o->info.handle = oseg.index;
550 #else
551 result = mpls_mpls_outsegment_add(g->mpls_handle, &o->info);
552 #endif
554 if (result != MPLS_SUCCESS) {
555 return result;
558 MPLS_REFCNT_HOLD(o);
559 o->switching = MPLS_BOOL_TRUE;
560 op = MPLS_LIST_HEAD(&g->outlabel);
561 while (op != NULL) {
562 if (op->index > o->index) {
563 MPLS_LIST_INSERT_BEFORE(&g->outlabel, op, o, _global);
564 return MPLS_SUCCESS;
566 op = MPLS_LIST_NEXT(&g->outlabel, op, _global);
568 MPLS_LIST_ADD_TAIL(&g->outlabel, o, _global, ldp_outlabel);
569 return MPLS_SUCCESS;
572 mpls_return_enum _ldp_global_del_outlabel(ldp_global * g, ldp_outlabel * o)
574 MPLS_ASSERT(g && o);
575 #if MPLS_USE_LSR
577 lsr_outsegment oseg;
578 oseg.index = o->info.handle;
579 lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_DEL);
581 #else
582 mpls_mpls_outsegment_del(g->mpls_handle, &o->info);
583 #endif
585 o->switching = MPLS_BOOL_FALSE;
586 MPLS_ASSERT(o->merge_count == 0);
587 MPLS_LIST_REMOVE(&g->outlabel, o, _global);
588 MPLS_REFCNT_RELEASE(o, ldp_outlabel_delete);
589 return MPLS_SUCCESS;
592 mpls_return_enum ldp_global_find_attr_index(ldp_global * g, uint32_t index,
593 ldp_attr ** attr)
595 ldp_attr *a = NULL;
597 if (g && index > 0) {
599 /* because we sort our inserts by index, this lets us know
600 if we've "walked" past the end of the list */
602 a = MPLS_LIST_TAIL(&g->attr);
603 if (a == NULL || a->index < index) {
604 return MPLS_END_OF_LIST;
605 *attr = NULL;
608 a = MPLS_LIST_HEAD(&g->attr);
609 while (a != NULL) {
610 if (a->index == index) {
611 *attr = a;
612 return MPLS_SUCCESS;
614 a = MPLS_LIST_NEXT(&g->attr, a, _global);
617 *attr = NULL;
618 return MPLS_FAILURE;
621 mpls_return_enum ldp_global_find_session_index(ldp_global * g, uint32_t index,
622 ldp_session ** session)
624 ldp_session *s = NULL;
626 if (g && index > 0) {
628 /* because we sort our inserts by index, this lets us know
629 if we've "walked" past the end of the list */
631 s = MPLS_LIST_TAIL(&g->session);
632 if (s == NULL || s->index < index) {
633 *session = NULL;
634 return MPLS_END_OF_LIST;
637 s = MPLS_LIST_HEAD(&g->session);
638 while (s != NULL) {
639 if (s->index == index) {
640 *session = s;
641 return MPLS_SUCCESS;
643 s = MPLS_LIST_NEXT(&g->session, s, _global);
646 *session = NULL;
647 return MPLS_FAILURE;
650 mpls_return_enum ldp_global_find_inlabel_index(ldp_global * g, uint32_t index,
651 ldp_inlabel ** inlabel)
653 ldp_inlabel *i = NULL;
655 if (g && index > 0) {
657 /* because we sort our inserts by index, this lets us know
658 if we've "walked" past the end of the list */
660 i = MPLS_LIST_TAIL(&g->inlabel);
661 if (i == NULL || i->index < index) {
662 *inlabel = NULL;
663 return MPLS_END_OF_LIST;
666 i = MPLS_LIST_HEAD(&g->inlabel);
667 while (i != NULL) {
668 if (i->index == index) {
669 *inlabel = i;
670 return MPLS_SUCCESS;
672 i = MPLS_LIST_NEXT(&g->inlabel, i, _global);
675 *inlabel = NULL;
676 return MPLS_FAILURE;
679 mpls_return_enum ldp_global_find_outlabel_index(ldp_global * g, uint32_t index,
680 ldp_outlabel ** outlabel)
682 ldp_outlabel *o = NULL;
684 if (g && index > 0) {
686 /* because we sort our inserts by index, this lets us know
687 if we've "walked" past the end of the list */
689 o = MPLS_LIST_TAIL(&g->outlabel);
690 if (o == NULL || o->index < index) {
691 *outlabel = NULL;
692 return MPLS_END_OF_LIST;
695 o = MPLS_LIST_HEAD(&g->outlabel);
696 while (o != NULL) {
697 if (o->index == index) {
698 *outlabel = o;
699 return MPLS_SUCCESS;
701 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
704 *outlabel = NULL;
705 return MPLS_FAILURE;
708 ldp_outlabel *ldp_global_find_outlabel_handle(ldp_global * g,
709 mpls_outsegment_handle handle)
711 ldp_outlabel *o = MPLS_LIST_HEAD(&g->outlabel);
713 if (g) {
714 while (o != NULL) {
715 if (!mpls_outsegment_handle_compare(o->info.handle, handle))
716 return o;
718 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
721 return NULL;
724 mpls_return_enum ldp_global_find_entity_index(ldp_global * g, uint32_t index,
725 ldp_entity ** entity)
727 ldp_entity *e = NULL;
729 if (g && index > 0) {
731 /* because we sort our inserts by index, this lets us know
732 if we've "walked" past the end of the list */
734 e = MPLS_LIST_TAIL(&g->entity);
735 if (e == NULL || e->index < index) {
736 *entity = NULL;
737 return MPLS_END_OF_LIST;
740 e = MPLS_LIST_HEAD(&g->entity);
741 while (e != NULL) {
742 if (e->index == index) {
743 *entity = e;
744 return MPLS_SUCCESS;
746 e = MPLS_LIST_NEXT(&g->entity, e, _global);
749 *entity = NULL;
750 return MPLS_FAILURE;
753 ldp_peer *ldp_global_find_peer_addr(ldp_global * g, mpls_inet_addr * addr)
755 ldp_peer *p;
757 MPLS_ASSERT(g && addr);
759 /* JLEU: we will need to add a tree to optimize this search,
760 known peers will be in tree, unknown will take a "slow path" to
761 verify them, then be added to tree */
763 p = MPLS_LIST_HEAD(&g->peer);
764 while (p) {
765 LDP_PRINT(g->user_data,
766 "ldp_global_find_peer_lsrid: peer: %08x lsrid: %08x\n",
767 p->dest.addr.u.ipv4, addr->u.ipv4);
768 if (!mpls_inet_addr_compare(&p->dest.addr, addr)) {
769 return p;
771 p = MPLS_LIST_NEXT(&g->peer, p, _global);
773 return NULL;
776 mpls_return_enum ldp_global_find_adj_index(ldp_global * g, uint32_t index,
777 ldp_adj ** adj)
779 ldp_adj *a = NULL;
781 if (g && index > 0) {
782 /* because we sort our inserts by index, this lets us know
783 if we've "walked" past the end of the list */
785 a = MPLS_LIST_TAIL(&g->adj);
786 if (a == NULL || a->index < index) {
787 return MPLS_END_OF_LIST;
788 *adj = NULL;
791 a = MPLS_LIST_HEAD(&g->adj);
792 while (a != NULL) {
793 if (a->index == index) {
794 *adj = a;
795 return MPLS_SUCCESS;
797 a = MPLS_LIST_NEXT(&g->adj, a, _global);
800 *adj = NULL;
801 return MPLS_FAILURE;
804 mpls_return_enum ldp_global_find_peer_index(ldp_global * g, uint32_t index,
805 ldp_peer ** peer)
807 ldp_peer *p = NULL;
809 if (g && index > 0) {
810 /* because we sort our inserts by index, this lets us know
811 if we've "walked" past the end of the list */
813 p = MPLS_LIST_TAIL(&g->peer);
814 if (p == NULL || p->index < index) {
815 *peer = NULL;
816 return MPLS_END_OF_LIST;
819 p = MPLS_LIST_HEAD(&g->peer);
820 while (p != NULL) {
821 if (p->index == index) {
822 *peer = p;
823 return MPLS_SUCCESS;
825 p = MPLS_LIST_NEXT(&g->peer, p, _global);
828 *peer = NULL;
829 return MPLS_FAILURE;
832 mpls_return_enum ldp_global_find_fec_index(ldp_global * g, uint32_t index,
833 ldp_fec ** fec)
835 ldp_fec *f = NULL;
837 if (g && index > 0) {
838 /* because we sort our inserts by index, this lets us know
839 if we've "walked" past the end of the list */
841 f = MPLS_LIST_TAIL(&g->fec);
842 if (f == NULL || f->index < index) {
843 *fec = NULL;
844 return MPLS_END_OF_LIST;
847 f = MPLS_LIST_HEAD(&g->fec);
848 while (f != NULL) {
849 if (f->index == index) {
850 *fec = f;
851 return MPLS_SUCCESS;
853 f = MPLS_LIST_NEXT(&g->fec, f, _global);
856 *fec = NULL;
857 return MPLS_FAILURE;
860 mpls_return_enum ldp_global_find_fec(ldp_global * g, mpls_fec * m,
861 ldp_fec ** fec)
863 ldp_fec *f = NULL;
865 MPLS_ASSERT(g && m);
867 f = MPLS_LIST_HEAD(&g->fec);
868 do {
869 if (!mpls_fec_compare(m, &f->info)) {
870 *fec = f;
871 return MPLS_SUCCESS;
873 } while((f = MPLS_LIST_NEXT(&g->fec, f, _global)));
874 *fec = NULL;
875 return MPLS_FAILURE;
878 mpls_return_enum ldp_global_find_addr_index(ldp_global * g, uint32_t index,
879 ldp_addr ** addr)
881 ldp_addr *a = NULL;
883 if (g && index > 0) {
885 /* because we sort our inserts by index, this lets us know
886 if we've "walked" past the end of the list */
888 a = MPLS_LIST_TAIL(&g->addr);
889 if (a == NULL || a->index < index) {
890 *addr = NULL;
891 return MPLS_END_OF_LIST;
894 a = MPLS_LIST_HEAD(&g->addr);
895 while (a != NULL) {
896 if (a->index == index) {
897 *addr = a;
898 return MPLS_SUCCESS;
900 a = MPLS_LIST_NEXT(&g->addr, a, _global);
903 *addr = NULL;
904 return MPLS_FAILURE;
907 mpls_return_enum ldp_global_find_if_index(ldp_global * g, uint32_t index,
908 ldp_if ** iff)
910 ldp_if *i = NULL;
912 if (g && index > 0) {
914 /* because we sort our inserts by index, this lets us know
915 if we've "walked" past the end of the list */
917 i = MPLS_LIST_TAIL(&g->iff);
918 if (i == NULL || i->index < index) {
919 *iff = NULL;
920 return MPLS_END_OF_LIST;
923 i = MPLS_LIST_HEAD(&g->iff);
924 while (i != NULL) {
925 if (i->index == index) {
926 *iff = i;
927 return MPLS_SUCCESS;
929 i = MPLS_LIST_NEXT(&g->iff, i, _global);
932 *iff = NULL;
933 return MPLS_FAILURE;
936 ldp_if *ldp_global_find_if_handle(ldp_global * g, mpls_if_handle handle)
938 ldp_if *i = MPLS_LIST_HEAD(&g->iff);
940 if (g) {
941 while (i != NULL) {
942 if (!mpls_if_handle_compare(i->handle, handle))
943 return i;
945 i = MPLS_LIST_NEXT(&g->iff, i, _global);
948 return NULL;
951 ldp_adj *ldp_global_find_adj_ldpid(ldp_global * g, mpls_inet_addr * lsraddr,
952 int labelspace)
955 ldp_adj *a = MPLS_LIST_HEAD(&g->adj);
957 while (a != NULL) {
958 if ((!mpls_inet_addr_compare(lsraddr, &a->remote_lsr_address)) &&
959 labelspace == a->remote_label_space)
960 return a;
962 a = MPLS_LIST_NEXT(&g->adj, a, _global);
964 return NULL;
967 mpls_return_enum ldp_global_find_tunnel_index(ldp_global * g, uint32_t index,
968 ldp_tunnel ** tunnel)
970 ldp_tunnel *t = NULL;
972 if (g && index > 0) {
973 /* because we sort our inserts by index, this lets us know
974 if we've "walked" past the end of the list */
976 t = MPLS_LIST_TAIL(&g->tunnel);
977 if (t == NULL || t->index < index) {
978 *tunnel = NULL;
979 return MPLS_END_OF_LIST;
982 t = MPLS_LIST_HEAD(&g->tunnel);
983 while (t != NULL) {
984 if (t->index == index) {
985 *tunnel = t;
986 return MPLS_SUCCESS;
988 t = MPLS_LIST_NEXT(&g->tunnel, t, _global);
991 *tunnel = NULL;
992 return MPLS_FAILURE;
995 mpls_return_enum ldp_global_find_resource_index(ldp_global * g, uint32_t index,
996 ldp_resource ** resource)
998 ldp_resource *r = NULL;
1000 if (g && index > 0) {
1001 /* because we sort our inserts by index, this lets us know
1002 if we've "walked" past the end of the list */
1004 r = MPLS_LIST_TAIL(&g->resource);
1005 if (r == NULL || r->index < index) {
1006 *resource = NULL;
1007 return MPLS_END_OF_LIST;
1010 r = MPLS_LIST_HEAD(&g->resource);
1011 while (r != NULL) {
1012 if (r->index == index) {
1013 *resource = r;
1014 return MPLS_SUCCESS;
1016 r = MPLS_LIST_NEXT(&g->resource, r, _global);
1019 *resource = NULL;
1020 return MPLS_FAILURE;
1023 mpls_return_enum ldp_global_find_hop_list_index(ldp_global * g, uint32_t index,
1024 ldp_hop_list ** hop_list)
1026 ldp_hop_list *h = NULL;
1028 if (g && index > 0) {
1029 /* because we sort our inserts by index, this lets us know
1030 if we've "walked" past the end of the list */
1032 h = MPLS_LIST_TAIL(&g->hop_list);
1033 if (h == NULL || h->index < index) {
1034 *hop_list = NULL;
1035 return MPLS_END_OF_LIST;
1038 h = MPLS_LIST_HEAD(&g->hop_list);
1039 while (h != NULL) {
1040 if (h->index == index) {
1041 *hop_list = h;
1042 return MPLS_SUCCESS;
1044 h = MPLS_LIST_NEXT(&g->hop_list, h, _global);
1047 *hop_list = NULL;
1048 return MPLS_FAILURE;
1051 void _ldp_global_add_tunnel(ldp_global * g, ldp_tunnel * t)
1053 ldp_tunnel *tp = NULL;
1055 MPLS_ASSERT(g && t);
1056 MPLS_REFCNT_HOLD(t);
1057 tp = MPLS_LIST_HEAD(&g->tunnel);
1058 while (tp != NULL) {
1059 if (tp->index > t->index) {
1060 MPLS_LIST_INSERT_BEFORE(&g->tunnel, tp, t, _global);
1061 return;
1063 tp = MPLS_LIST_NEXT(&g->tunnel, tp, _global);
1065 MPLS_LIST_ADD_TAIL(&g->tunnel, t, _global, ldp_tunnel);
1068 void _ldp_global_del_tunnel(ldp_global * g, ldp_tunnel * t)
1070 MPLS_ASSERT(g && t);
1071 MPLS_LIST_REMOVE(&g->tunnel, t, _global);
1072 MPLS_REFCNT_RELEASE(t, ldp_tunnel_delete);
1075 void _ldp_global_add_resource(ldp_global * g, ldp_resource * r)
1077 ldp_resource *rp = NULL;
1079 MPLS_ASSERT(g && r);
1080 MPLS_REFCNT_HOLD(r);
1081 rp = MPLS_LIST_HEAD(&g->resource);
1082 while (rp != NULL) {
1083 if (rp->index > r->index) {
1084 MPLS_LIST_INSERT_BEFORE(&g->resource, rp, r, _global);
1085 return;
1087 rp = MPLS_LIST_NEXT(&g->resource, rp, _global);
1089 MPLS_LIST_ADD_TAIL(&g->resource, r, _global, ldp_resource);
1092 void _ldp_global_del_resource(ldp_global * g, ldp_resource * r)
1094 MPLS_ASSERT(g && r);
1095 MPLS_LIST_REMOVE(&g->resource, r, _global);
1096 MPLS_REFCNT_RELEASE(r, ldp_resource_delete);
1099 void _ldp_global_add_hop_list(ldp_global * g, ldp_hop_list * h)
1101 ldp_hop_list *hp = NULL;
1103 MPLS_ASSERT(g && h);
1104 MPLS_REFCNT_HOLD(h);
1105 hp = MPLS_LIST_HEAD(&g->hop_list);
1106 while (hp != NULL) {
1107 if (hp->index > h->index) {
1108 MPLS_LIST_INSERT_BEFORE(&g->hop_list, hp, h, _global);
1109 return;
1111 hp = MPLS_LIST_NEXT(&g->hop_list, hp, _global);
1113 MPLS_LIST_ADD_TAIL(&g->hop_list, h, _global, ldp_hop_list);
1116 void _ldp_global_del_hop_list(ldp_global * g, ldp_hop_list * h)
1118 MPLS_ASSERT(g && h);
1119 MPLS_LIST_REMOVE(&g->hop_list, h, _global);
1120 MPLS_REFCNT_RELEASE(h, ldp_hop_list_delete);
1123 void _ldp_global_add_fec(ldp_global * g, ldp_fec * f)
1125 ldp_fec *fp = NULL;
1127 MPLS_ASSERT(g && f);
1129 * TESTING: jleu 6/7/2004, since I want the FEC to be cleaned up
1130 * when it no longer has a nexthop, addr, or label, the only things that
1131 * should increment the ref are those (nh, addr, label etc), not global
1132 * nor inserting into the tree. I also added this comment in
1133 * ldp_fec_create()
1134 MPLS_REFCNT_HOLD(f);
1136 fp = MPLS_LIST_HEAD(&g->fec);
1137 while (fp != NULL) {
1138 if (fp->index > f->index) {
1139 MPLS_LIST_INSERT_BEFORE(&g->fec, fp, f, _global);
1140 return;
1142 fp = MPLS_LIST_NEXT(&g->fec, fp, _global);
1144 MPLS_LIST_ADD_TAIL(&g->fec, f, _global, ldp_fec);
1147 void _ldp_global_del_fec(ldp_global * g, ldp_fec * f)
1149 MPLS_ASSERT(g && f);
1150 MPLS_LIST_REMOVE(&g->fec, f, _global);
1153 void _ldp_global_add_nexthop(ldp_global * g, ldp_nexthop * nh)
1155 ldp_nexthop *nhp = NULL;
1157 MPLS_ASSERT(g && nh);
1158 nhp = MPLS_LIST_HEAD(&g->nexthop);
1159 while (nhp != NULL) {
1160 if (nhp->index > nh->index) {
1161 MPLS_LIST_INSERT_BEFORE(&g->nexthop, nhp, nh, _global);
1162 return;
1164 nhp = MPLS_LIST_NEXT(&g->nexthop, nhp, _global);
1166 MPLS_LIST_ADD_TAIL(&g->nexthop, nh, _global, ldp_nexthop);
1169 void _ldp_global_del_nexthop(ldp_global * g, ldp_nexthop * nh)
1171 MPLS_ASSERT(g && nh);
1172 MPLS_LIST_REMOVE(&g->nexthop, nh, _global);