Add additional comments
[mpls-ldp-portable.git] / ldp / ldp_global.c
blobf8aa6923c7c94b71617135b54dc221546d53a7b4
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 ldp_fec *fp;
293 ldp_fec *nfp;
294 ldp_if *ifp;
295 ldp_if *nifp;
296 ldp_addr *ap;
297 ldp_addr *nap;
298 ldp_nexthop *nhp;
299 ldp_nexthop *nnhp;
300 ldp_attr *atp;
301 ldp_attr *natp;
302 ldp_entity *ep;
303 ldp_entity *nep;
305 if (g) {
306 /* clean up the entities that were configured, sessions and adj should
307 * already have been cleaned up when the entity was shutdown
309 ep = MPLS_LIST_HEAD(&g->entity);
310 while (ep != NULL) {
311 nep = MPLS_LIST_NEXT(&g->entity, ep, _global);
312 switch (ep->entity_type) {
313 case LDP_DIRECT:
314 ldp_entity_del_if(g,ep);
315 break;
316 case LDP_INDIRECT:
317 ldp_entity_del_peer(ep);
318 break;
319 default:
320 MPLS_ASSERT(0);
322 _ldp_global_del_entity(g, ep);
323 ep = nep;
326 /* need to properly purge FECs/nexthops/interfaces/addresses */
328 fp = MPLS_LIST_HEAD(&g->fec);
329 while (fp != NULL) {
330 nfp = MPLS_LIST_NEXT(&g->fec, fp, _global);
332 nhp = MPLS_LIST_HEAD(&fp->nh_root);
333 while (nhp) {
334 nnhp = MPLS_LIST_NEXT(&fp->nh_root, nhp, _fec);
335 ldp_fec_del_nexthop(g, fp, nhp);
336 nhp = nnhp;
338 MPLS_REFCNT_RELEASE2(g, fp, ldp_fec_delete);
340 fp = nfp;
343 ifp = MPLS_LIST_HEAD(&g->iff);
344 while (ifp != NULL) {
345 nifp = MPLS_LIST_NEXT(&g->iff, ifp, _global);
347 ap = MPLS_LIST_HEAD(&ifp->addr_root);
348 while (ap != NULL) {
349 nap = MPLS_LIST_NEXT(&ifp->addr_root, ap, _if);
350 ldp_if_del_addr(g, ifp, ap);
351 ap = nap;
353 MPLS_REFCNT_RELEASE2(g, ifp, ldp_if_delete);
355 ifp = nifp;
358 nhp = MPLS_LIST_HEAD(&g->nexthop);
359 while (nhp != NULL) {
360 fprintf(stderr,"Left over NH: %p\n", nhp);
361 nnhp = MPLS_LIST_NEXT(&g->nexthop, nhp, _global);
362 _ldp_global_del_nexthop(g, nhp);
363 nhp = nnhp;
366 ap = MPLS_LIST_HEAD(&g->addr);
367 while (ap != NULL) {
368 fprintf(stderr,"Left over ADDR: %p\n", ap);
369 nap = MPLS_LIST_NEXT(&g->addr, ap, _global);
370 _ldp_global_del_addr(g, ap);
371 ap = nap;
374 atp = MPLS_LIST_HEAD(&g->attr);
375 while (atp != NULL) {
376 fprintf(stderr,"Left over ATTR: %p\n", atp);
377 natp = MPLS_LIST_NEXT(&g->attr, atp, _global);
378 _ldp_global_del_attr(g, atp);
379 atp = natp;
382 mpls_tree_delete(g->addr_tree);
383 mpls_tree_delete(g->fec_tree);
385 mpls_lock_delete(g->global_lock);
386 LDP_PRINT(g->user_data, "global delete\n");
387 mpls_free(g);
389 return MPLS_SUCCESS;
392 void _ldp_global_add_attr(ldp_global * g, ldp_attr * a)
394 ldp_attr *ap = NULL;
396 MPLS_ASSERT(g && a);
397 MPLS_REFCNT_HOLD(a);
398 ap = MPLS_LIST_HEAD(&g->attr);
399 while (ap != NULL) {
400 if (ap->index > a->index) {
401 MPLS_LIST_INSERT_BEFORE(&g->attr, ap, a, _global);
402 return;
404 ap = MPLS_LIST_NEXT(&g->attr, ap, _global);
406 MPLS_LIST_ADD_TAIL(&g->attr, a, _global, ldp_attr);
409 void _ldp_global_del_attr(ldp_global * g, ldp_attr * a)
411 MPLS_ASSERT(g && a);
412 MPLS_LIST_REMOVE(&g->attr, a, _global);
413 MPLS_REFCNT_RELEASE(a, ldp_attr_delete);
416 void _ldp_global_add_peer(ldp_global * g, ldp_peer * p)
418 ldp_peer *pp = NULL;
420 MPLS_ASSERT(g && p);
421 MPLS_REFCNT_HOLD(p);
422 pp = MPLS_LIST_HEAD(&g->peer);
423 while (pp != NULL) {
424 if (pp->index > p->index) {
425 MPLS_LIST_INSERT_BEFORE(&g->peer, pp, p, _global);
426 return;
428 pp = MPLS_LIST_NEXT(&g->peer, pp, _global);
430 MPLS_LIST_ADD_TAIL(&g->peer, p, _global, ldp_peer);
433 void _ldp_global_del_peer(ldp_global * g, ldp_peer * p)
435 MPLS_ASSERT(g && p);
436 MPLS_LIST_REMOVE(&g->peer, p, _global);
437 MPLS_REFCNT_RELEASE(p, ldp_peer_delete);
441 * _ldp_global_add_if/del_if and _ldp_global_add_addr/del_addr are
442 * not the same as the rest of the global_add/del functions. They
443 * do not hold refcnts, they are used as part of the create and delete
444 * process of these structures
447 void _ldp_global_add_if(ldp_global * g, ldp_if * i)
449 ldp_if *ip = NULL;
451 MPLS_ASSERT(g && i);
452 ip = MPLS_LIST_HEAD(&g->iff);
453 while (ip != NULL) {
454 if (ip->index > i->index) {
455 MPLS_LIST_INSERT_BEFORE(&g->iff, ip, i, _global);
456 return;
458 ip = MPLS_LIST_NEXT(&g->iff, ip, _global);
460 MPLS_LIST_ADD_TAIL(&g->iff, i, _global, ldp_if);
463 void _ldp_global_del_if(ldp_global * g, ldp_if * i)
465 MPLS_ASSERT(g && i);
466 MPLS_LIST_REMOVE(&g->iff, i, _global);
469 void _ldp_global_add_addr(ldp_global * g, ldp_addr * a)
471 ldp_addr *ap = NULL;
473 MPLS_ASSERT(g && a);
474 ap = MPLS_LIST_HEAD(&g->addr);
475 while (ap != NULL) {
476 if (ap->index > a->index) {
477 MPLS_LIST_INSERT_BEFORE(&g->addr, ap, a, _global);
478 return;
480 ap = MPLS_LIST_NEXT(&g->addr, ap, _global);
482 MPLS_LIST_ADD_TAIL(&g->addr, a, _global, ldp_addr);
485 void _ldp_global_del_addr(ldp_global * g, ldp_addr * a)
487 MPLS_ASSERT(g && a);
488 MPLS_LIST_REMOVE(&g->addr, a, _global);
491 void _ldp_global_add_adj(ldp_global * g, ldp_adj * a)
493 ldp_adj *ap = NULL;
495 MPLS_ASSERT(g && a);
496 MPLS_REFCNT_HOLD(a);
497 ap = MPLS_LIST_HEAD(&g->adj);
498 while (ap != NULL) {
499 if (ap->index > a->index) {
500 MPLS_LIST_INSERT_BEFORE(&g->adj, ap, a, _global);
501 return;
503 ap = MPLS_LIST_NEXT(&g->adj, ap, _global);
505 MPLS_LIST_ADD_TAIL(&g->adj, a, _global, ldp_adj);
508 void _ldp_global_del_adj(ldp_global * g, ldp_adj * a)
510 MPLS_ASSERT(g && a);
511 MPLS_LIST_REMOVE(&g->adj, a, _global);
512 MPLS_REFCNT_RELEASE(a, ldp_adj_delete);
515 void _ldp_global_add_entity(ldp_global * g, ldp_entity * e)
517 ldp_entity *ep = NULL;
519 MPLS_ASSERT(g && e);
520 MPLS_REFCNT_HOLD(e);
521 ep = MPLS_LIST_HEAD(&g->entity);
522 while (ep != NULL) {
523 if (ep->index > e->index) {
524 MPLS_LIST_INSERT_BEFORE(&g->entity, ep, e, _global);
525 return;
527 ep = MPLS_LIST_NEXT(&g->entity, ep, _global);
529 MPLS_LIST_ADD_TAIL(&g->entity, e, _global, ldp_entity);
532 void _ldp_global_del_entity(ldp_global * g, ldp_entity * e)
534 MPLS_ASSERT(g && e);
535 MPLS_LIST_REMOVE(&g->entity, e, _global);
536 MPLS_REFCNT_RELEASE(e, ldp_entity_delete);
539 void _ldp_global_add_session(ldp_global * g, ldp_session * s)
541 ldp_session *sp = NULL;
543 MPLS_ASSERT(g && s);
544 MPLS_REFCNT_HOLD(s);
545 s->on_global = MPLS_BOOL_TRUE;
546 sp = MPLS_LIST_HEAD(&g->session);
547 while (sp != NULL) {
548 if (sp->index > s->index) {
549 MPLS_LIST_INSERT_BEFORE(&g->session, sp, s, _global);
550 return;
552 sp = MPLS_LIST_NEXT(&g->session, sp, _global);
554 MPLS_LIST_ADD_TAIL(&g->session, s, _global, ldp_session);
557 void _ldp_global_del_session(ldp_global * g, ldp_session * s)
559 MPLS_ASSERT(g && s);
560 MPLS_ASSERT(s->on_global == MPLS_BOOL_TRUE);
561 MPLS_LIST_REMOVE(&g->session, s, _global);
562 s->on_global = MPLS_BOOL_FALSE;
563 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
566 mpls_return_enum _ldp_global_add_inlabel(ldp_global * g, ldp_inlabel * i)
568 ldp_inlabel *ip = NULL;
569 mpls_return_enum result;
571 MPLS_ASSERT(g && i);
573 #if MPLS_USE_LSR
575 lsr_insegment iseg;
576 memcpy(&iseg.info,&i->info,sizeof(mpls_insegment));
577 result = lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_ADD|
578 LSR_INSEGMENT_CFG_NPOP|LSR_INSEGMENT_CFG_FAMILY|
579 LSR_INSEGMENT_CFG_LABELSPACE|LSR_INSEGMENT_CFG_LABEL|
580 LSR_INSEGMENT_CFG_OWNER);
581 memcpy(&i->info, &iseg.info, sizeof(mpls_insegment));
582 i->info.handle = iseg.index;
584 #else
585 result = mpls_mpls_insegment_add(g->mpls_handle, &i->info);
586 #endif
587 if (result != MPLS_SUCCESS) {
588 return result;
591 MPLS_REFCNT_HOLD(i);
592 ip = MPLS_LIST_HEAD(&g->inlabel);
593 while (ip != NULL) {
594 if (ip->index > i->index) {
595 MPLS_LIST_INSERT_BEFORE(&g->inlabel, ip, i, _global);
596 return MPLS_SUCCESS;
598 ip = MPLS_LIST_NEXT(&g->inlabel, ip, _global);
600 MPLS_LIST_ADD_TAIL(&g->inlabel, i, _global, ldp_inlabel);
601 return MPLS_SUCCESS;
604 mpls_return_enum _ldp_global_del_inlabel(ldp_global * g, ldp_inlabel * i)
606 MPLS_ASSERT(g && i);
607 MPLS_ASSERT(i->reuse_count == 0);
608 #if MPLS_USE_LSR
610 lsr_insegment iseg;
611 iseg.index = i->info.handle;
612 lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_DEL);
614 #else
615 mpls_mpls_insegment_del(g->mpls_handle, &i->info);
616 #endif
617 MPLS_LIST_REMOVE(&g->inlabel, i, _global);
618 MPLS_REFCNT_RELEASE(i, ldp_inlabel_delete);
619 return MPLS_SUCCESS;
622 mpls_return_enum _ldp_global_add_outlabel(ldp_global * g, ldp_outlabel * o)
624 ldp_outlabel *op = NULL;
625 mpls_return_enum result;
627 MPLS_ASSERT(g && o);
628 #if MPLS_USE_LSR
630 lsr_outsegment oseg;
631 memcpy(&oseg.info, &o->info, sizeof(mpls_outsegment));
632 result = lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_ADD|
633 LSR_OUTSEGMENT_CFG_PUSH_LABEL|LSR_OUTSEGMENT_CFG_OWNER|
634 LSR_OUTSEGMENT_CFG_INTERFACE|LSR_OUTSEGMENT_CFG_LABEL|
635 LSR_OUTSEGMENT_CFG_NEXTHOP);
636 o->info.handle = oseg.index;
638 #else
639 result = mpls_mpls_outsegment_add(g->mpls_handle, &o->info);
640 #endif
642 if (result != MPLS_SUCCESS) {
643 return result;
646 MPLS_REFCNT_HOLD(o);
647 o->switching = MPLS_BOOL_TRUE;
648 op = MPLS_LIST_HEAD(&g->outlabel);
649 while (op != NULL) {
650 if (op->index > o->index) {
651 MPLS_LIST_INSERT_BEFORE(&g->outlabel, op, o, _global);
652 return MPLS_SUCCESS;
654 op = MPLS_LIST_NEXT(&g->outlabel, op, _global);
656 MPLS_LIST_ADD_TAIL(&g->outlabel, o, _global, ldp_outlabel);
657 return MPLS_SUCCESS;
660 mpls_return_enum _ldp_global_del_outlabel(ldp_global * g, ldp_outlabel * o)
662 MPLS_ASSERT(g && o);
663 #if MPLS_USE_LSR
665 lsr_outsegment oseg;
666 oseg.index = o->info.handle;
667 lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_DEL);
669 #else
670 mpls_mpls_outsegment_del(g->mpls_handle, &o->info);
671 #endif
673 o->switching = MPLS_BOOL_FALSE;
674 MPLS_ASSERT(o->merge_count == 0);
675 MPLS_LIST_REMOVE(&g->outlabel, o, _global);
676 MPLS_REFCNT_RELEASE(o, ldp_outlabel_delete);
677 return MPLS_SUCCESS;
680 mpls_return_enum ldp_global_find_attr_index(ldp_global * g, uint32_t index,
681 ldp_attr ** attr)
683 ldp_attr *a = NULL;
685 if (g && index > 0) {
687 /* because we sort our inserts by index, this lets us know
688 if we've "walked" past the end of the list */
690 a = MPLS_LIST_TAIL(&g->attr);
691 if (a == NULL || a->index < index) {
692 return MPLS_END_OF_LIST;
693 *attr = NULL;
696 a = MPLS_LIST_HEAD(&g->attr);
697 while (a != NULL) {
698 if (a->index == index) {
699 *attr = a;
700 return MPLS_SUCCESS;
702 a = MPLS_LIST_NEXT(&g->attr, a, _global);
705 *attr = NULL;
706 return MPLS_FAILURE;
709 mpls_return_enum ldp_global_find_session_index(ldp_global * g, uint32_t index,
710 ldp_session ** session)
712 ldp_session *s = NULL;
714 if (g && index > 0) {
716 /* because we sort our inserts by index, this lets us know
717 if we've "walked" past the end of the list */
719 s = MPLS_LIST_TAIL(&g->session);
720 if (s == NULL || s->index < index) {
721 *session = NULL;
722 return MPLS_END_OF_LIST;
725 s = MPLS_LIST_HEAD(&g->session);
726 while (s != NULL) {
727 if (s->index == index) {
728 *session = s;
729 return MPLS_SUCCESS;
731 s = MPLS_LIST_NEXT(&g->session, s, _global);
734 *session = NULL;
735 return MPLS_FAILURE;
738 mpls_return_enum ldp_global_find_inlabel_index(ldp_global * g, uint32_t index,
739 ldp_inlabel ** inlabel)
741 ldp_inlabel *i = NULL;
743 if (g && index > 0) {
745 /* because we sort our inserts by index, this lets us know
746 if we've "walked" past the end of the list */
748 i = MPLS_LIST_TAIL(&g->inlabel);
749 if (i == NULL || i->index < index) {
750 *inlabel = NULL;
751 return MPLS_END_OF_LIST;
754 i = MPLS_LIST_HEAD(&g->inlabel);
755 while (i != NULL) {
756 if (i->index == index) {
757 *inlabel = i;
758 return MPLS_SUCCESS;
760 i = MPLS_LIST_NEXT(&g->inlabel, i, _global);
763 *inlabel = NULL;
764 return MPLS_FAILURE;
767 mpls_return_enum ldp_global_find_outlabel_index(ldp_global * g, uint32_t index,
768 ldp_outlabel ** outlabel)
770 ldp_outlabel *o = NULL;
772 if (g && index > 0) {
774 /* because we sort our inserts by index, this lets us know
775 if we've "walked" past the end of the list */
777 o = MPLS_LIST_TAIL(&g->outlabel);
778 if (o == NULL || o->index < index) {
779 *outlabel = NULL;
780 return MPLS_END_OF_LIST;
783 o = MPLS_LIST_HEAD(&g->outlabel);
784 while (o != NULL) {
785 if (o->index == index) {
786 *outlabel = o;
787 return MPLS_SUCCESS;
789 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
792 *outlabel = NULL;
793 return MPLS_FAILURE;
796 ldp_outlabel *ldp_global_find_outlabel_handle(ldp_global * g,
797 mpls_outsegment_handle handle)
799 ldp_outlabel *o = MPLS_LIST_HEAD(&g->outlabel);
801 if (g) {
802 while (o != NULL) {
803 if (!mpls_outsegment_handle_compare(o->info.handle, handle))
804 return o;
806 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
809 return NULL;
812 mpls_return_enum ldp_global_find_entity_index(ldp_global * g, uint32_t index,
813 ldp_entity ** entity)
815 ldp_entity *e = NULL;
817 if (g && index > 0) {
819 /* because we sort our inserts by index, this lets us know
820 if we've "walked" past the end of the list */
822 e = MPLS_LIST_TAIL(&g->entity);
823 if (e == NULL || e->index < index) {
824 *entity = NULL;
825 return MPLS_END_OF_LIST;
828 e = MPLS_LIST_HEAD(&g->entity);
829 while (e != NULL) {
830 if (e->index == index) {
831 *entity = e;
832 return MPLS_SUCCESS;
834 e = MPLS_LIST_NEXT(&g->entity, e, _global);
837 *entity = NULL;
838 return MPLS_FAILURE;
841 ldp_peer *ldp_global_find_peer_addr(ldp_global * g, mpls_inet_addr * addr)
843 ldp_peer *p;
845 MPLS_ASSERT(g && addr);
847 /* JLEU: we will need to add a tree to optimize this search,
848 known peers will be in tree, unknown will take a "slow path" to
849 verify them, then be added to tree */
851 p = MPLS_LIST_HEAD(&g->peer);
852 while (p) {
853 LDP_PRINT(g->user_data,
854 "ldp_global_find_peer_lsrid: peer: %08x lsrid: %08x\n",
855 p->dest.addr.u.ipv4, addr->u.ipv4);
856 if (!mpls_inet_addr_compare(&p->dest.addr, addr)) {
857 return p;
859 p = MPLS_LIST_NEXT(&g->peer, p, _global);
861 return NULL;
864 mpls_return_enum ldp_global_find_adj_index(ldp_global * g, uint32_t index,
865 ldp_adj ** adj)
867 ldp_adj *a = NULL;
869 if (g && index > 0) {
870 /* because we sort our inserts by index, this lets us know
871 if we've "walked" past the end of the list */
873 a = MPLS_LIST_TAIL(&g->adj);
874 if (a == NULL || a->index < index) {
875 return MPLS_END_OF_LIST;
876 *adj = NULL;
879 a = MPLS_LIST_HEAD(&g->adj);
880 while (a != NULL) {
881 if (a->index == index) {
882 *adj = a;
883 return MPLS_SUCCESS;
885 a = MPLS_LIST_NEXT(&g->adj, a, _global);
888 *adj = NULL;
889 return MPLS_FAILURE;
892 mpls_return_enum ldp_global_find_peer_index(ldp_global * g, uint32_t index,
893 ldp_peer ** peer)
895 ldp_peer *p = NULL;
897 if (g && index > 0) {
898 /* because we sort our inserts by index, this lets us know
899 if we've "walked" past the end of the list */
901 p = MPLS_LIST_TAIL(&g->peer);
902 if (p == NULL || p->index < index) {
903 *peer = NULL;
904 return MPLS_END_OF_LIST;
907 p = MPLS_LIST_HEAD(&g->peer);
908 while (p != NULL) {
909 if (p->index == index) {
910 *peer = p;
911 return MPLS_SUCCESS;
913 p = MPLS_LIST_NEXT(&g->peer, p, _global);
916 *peer = NULL;
917 return MPLS_FAILURE;
920 mpls_return_enum ldp_global_find_fec_index(ldp_global * g, uint32_t index,
921 ldp_fec ** fec)
923 ldp_fec *f = NULL;
925 if (g && index > 0) {
926 /* because we sort our inserts by index, this lets us know
927 if we've "walked" past the end of the list */
929 f = MPLS_LIST_TAIL(&g->fec);
930 if (f == NULL || f->index < index) {
931 *fec = NULL;
932 return MPLS_END_OF_LIST;
935 f = MPLS_LIST_HEAD(&g->fec);
936 while (f != NULL) {
937 if (f->index == index) {
938 *fec = f;
939 return MPLS_SUCCESS;
941 f = MPLS_LIST_NEXT(&g->fec, f, _global);
944 *fec = NULL;
945 return MPLS_FAILURE;
948 mpls_return_enum ldp_global_find_fec(ldp_global * g, mpls_fec * m,
949 ldp_fec ** fec)
951 ldp_fec *f = NULL;
953 MPLS_ASSERT(g && m);
955 f = MPLS_LIST_HEAD(&g->fec);
956 do {
957 if (!mpls_fec_compare(m, &f->info)) {
958 *fec = f;
959 return MPLS_SUCCESS;
961 } while((f = MPLS_LIST_NEXT(&g->fec, f, _global)));
962 *fec = NULL;
963 return MPLS_FAILURE;
966 mpls_return_enum ldp_global_find_addr_index(ldp_global * g, uint32_t index,
967 ldp_addr ** addr)
969 ldp_addr *a = NULL;
971 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 a = MPLS_LIST_TAIL(&g->addr);
977 if (a == NULL || a->index < index) {
978 *addr = NULL;
979 return MPLS_END_OF_LIST;
982 a = MPLS_LIST_HEAD(&g->addr);
983 while (a != NULL) {
984 if (a->index == index) {
985 *addr = a;
986 return MPLS_SUCCESS;
988 a = MPLS_LIST_NEXT(&g->addr, a, _global);
991 *addr = NULL;
992 return MPLS_FAILURE;
995 mpls_return_enum ldp_global_find_if_index(ldp_global * g, uint32_t index,
996 ldp_if ** iff)
998 ldp_if *i = NULL;
1000 if (g && index > 0) {
1002 /* because we sort our inserts by index, this lets us know
1003 if we've "walked" past the end of the list */
1005 i = MPLS_LIST_TAIL(&g->iff);
1006 if (i == NULL || i->index < index) {
1007 *iff = NULL;
1008 return MPLS_END_OF_LIST;
1011 i = MPLS_LIST_HEAD(&g->iff);
1012 while (i != NULL) {
1013 if (i->index == index) {
1014 *iff = i;
1015 return MPLS_SUCCESS;
1017 i = MPLS_LIST_NEXT(&g->iff, i, _global);
1020 *iff = NULL;
1021 return MPLS_FAILURE;
1024 ldp_if *ldp_global_find_if_handle(ldp_global * g, mpls_if_handle handle)
1026 ldp_if *i = MPLS_LIST_HEAD(&g->iff);
1028 if (g) {
1029 while (i != NULL) {
1030 if (!mpls_if_handle_compare(i->handle, handle))
1031 return i;
1033 i = MPLS_LIST_NEXT(&g->iff, i, _global);
1036 return NULL;
1039 ldp_adj *ldp_global_find_adj_ldpid(ldp_global * g, mpls_inet_addr * lsraddr,
1040 int labelspace)
1043 ldp_adj *a = MPLS_LIST_HEAD(&g->adj);
1045 while (a != NULL) {
1046 if ((!mpls_inet_addr_compare(lsraddr, &a->remote_lsr_address)) &&
1047 labelspace == a->remote_label_space)
1048 return a;
1050 a = MPLS_LIST_NEXT(&g->adj, a, _global);
1052 return NULL;
1055 mpls_return_enum ldp_global_find_tunnel_index(ldp_global * g, uint32_t index,
1056 ldp_tunnel ** tunnel)
1058 ldp_tunnel *t = NULL;
1060 if (g && index > 0) {
1061 /* because we sort our inserts by index, this lets us know
1062 if we've "walked" past the end of the list */
1064 t = MPLS_LIST_TAIL(&g->tunnel);
1065 if (t == NULL || t->index < index) {
1066 *tunnel = NULL;
1067 return MPLS_END_OF_LIST;
1070 t = MPLS_LIST_HEAD(&g->tunnel);
1071 while (t != NULL) {
1072 if (t->index == index) {
1073 *tunnel = t;
1074 return MPLS_SUCCESS;
1076 t = MPLS_LIST_NEXT(&g->tunnel, t, _global);
1079 *tunnel = NULL;
1080 return MPLS_FAILURE;
1083 mpls_return_enum ldp_global_find_resource_index(ldp_global * g, uint32_t index,
1084 ldp_resource ** resource)
1086 ldp_resource *r = NULL;
1088 if (g && index > 0) {
1089 /* because we sort our inserts by index, this lets us know
1090 if we've "walked" past the end of the list */
1092 r = MPLS_LIST_TAIL(&g->resource);
1093 if (r == NULL || r->index < index) {
1094 *resource = NULL;
1095 return MPLS_END_OF_LIST;
1098 r = MPLS_LIST_HEAD(&g->resource);
1099 while (r != NULL) {
1100 if (r->index == index) {
1101 *resource = r;
1102 return MPLS_SUCCESS;
1104 r = MPLS_LIST_NEXT(&g->resource, r, _global);
1107 *resource = NULL;
1108 return MPLS_FAILURE;
1111 mpls_return_enum ldp_global_find_hop_list_index(ldp_global * g, uint32_t index,
1112 ldp_hop_list ** hop_list)
1114 ldp_hop_list *h = NULL;
1116 if (g && index > 0) {
1117 /* because we sort our inserts by index, this lets us know
1118 if we've "walked" past the end of the list */
1120 h = MPLS_LIST_TAIL(&g->hop_list);
1121 if (h == NULL || h->index < index) {
1122 *hop_list = NULL;
1123 return MPLS_END_OF_LIST;
1126 h = MPLS_LIST_HEAD(&g->hop_list);
1127 while (h != NULL) {
1128 if (h->index == index) {
1129 *hop_list = h;
1130 return MPLS_SUCCESS;
1132 h = MPLS_LIST_NEXT(&g->hop_list, h, _global);
1135 *hop_list = NULL;
1136 return MPLS_FAILURE;
1139 void _ldp_global_add_tunnel(ldp_global * g, ldp_tunnel * t)
1141 ldp_tunnel *tp = NULL;
1143 MPLS_ASSERT(g && t);
1144 MPLS_REFCNT_HOLD(t);
1145 tp = MPLS_LIST_HEAD(&g->tunnel);
1146 while (tp != NULL) {
1147 if (tp->index > t->index) {
1148 MPLS_LIST_INSERT_BEFORE(&g->tunnel, tp, t, _global);
1149 return;
1151 tp = MPLS_LIST_NEXT(&g->tunnel, tp, _global);
1153 MPLS_LIST_ADD_TAIL(&g->tunnel, t, _global, ldp_tunnel);
1156 void _ldp_global_del_tunnel(ldp_global * g, ldp_tunnel * t)
1158 MPLS_ASSERT(g && t);
1159 MPLS_LIST_REMOVE(&g->tunnel, t, _global);
1160 MPLS_REFCNT_RELEASE(t, ldp_tunnel_delete);
1163 void _ldp_global_add_resource(ldp_global * g, ldp_resource * r)
1165 ldp_resource *rp = NULL;
1167 MPLS_ASSERT(g && r);
1168 MPLS_REFCNT_HOLD(r);
1169 rp = MPLS_LIST_HEAD(&g->resource);
1170 while (rp != NULL) {
1171 if (rp->index > r->index) {
1172 MPLS_LIST_INSERT_BEFORE(&g->resource, rp, r, _global);
1173 return;
1175 rp = MPLS_LIST_NEXT(&g->resource, rp, _global);
1177 MPLS_LIST_ADD_TAIL(&g->resource, r, _global, ldp_resource);
1180 void _ldp_global_del_resource(ldp_global * g, ldp_resource * r)
1182 MPLS_ASSERT(g && r);
1183 MPLS_LIST_REMOVE(&g->resource, r, _global);
1184 MPLS_REFCNT_RELEASE(r, ldp_resource_delete);
1187 void _ldp_global_add_hop_list(ldp_global * g, ldp_hop_list * h)
1189 ldp_hop_list *hp = NULL;
1191 MPLS_ASSERT(g && h);
1192 MPLS_REFCNT_HOLD(h);
1193 hp = MPLS_LIST_HEAD(&g->hop_list);
1194 while (hp != NULL) {
1195 if (hp->index > h->index) {
1196 MPLS_LIST_INSERT_BEFORE(&g->hop_list, hp, h, _global);
1197 return;
1199 hp = MPLS_LIST_NEXT(&g->hop_list, hp, _global);
1201 MPLS_LIST_ADD_TAIL(&g->hop_list, h, _global, ldp_hop_list);
1204 void _ldp_global_del_hop_list(ldp_global * g, ldp_hop_list * h)
1206 MPLS_ASSERT(g && h);
1207 MPLS_LIST_REMOVE(&g->hop_list, h, _global);
1208 MPLS_REFCNT_RELEASE(h, ldp_hop_list_delete);
1211 void _ldp_global_add_fec(ldp_global * g, ldp_fec * f)
1213 ldp_fec *fp = NULL;
1215 MPLS_ASSERT(g && f);
1217 * TESTING: jleu 6/7/2004, since I want the FEC to be cleaned up
1218 * when it no longer has a nexthop, addr, or label, the only things that
1219 * should increment the ref are those (nh, addr, label etc), not global
1220 * nor inserting into the tree. I also added this comment in
1221 * ldp_fec_create()
1222 MPLS_REFCNT_HOLD(f);
1224 fp = MPLS_LIST_HEAD(&g->fec);
1225 while (fp != NULL) {
1226 if (fp->index > f->index) {
1227 MPLS_LIST_INSERT_BEFORE(&g->fec, fp, f, _global);
1228 return;
1230 fp = MPLS_LIST_NEXT(&g->fec, fp, _global);
1232 MPLS_LIST_ADD_TAIL(&g->fec, f, _global, ldp_fec);
1235 void _ldp_global_del_fec(ldp_global * g, ldp_fec * f)
1237 MPLS_ASSERT(g && f);
1238 MPLS_LIST_REMOVE(&g->fec, f, _global);
1241 void _ldp_global_add_nexthop(ldp_global * g, ldp_nexthop * nh)
1243 ldp_nexthop *nhp = NULL;
1245 MPLS_ASSERT(g && nh);
1246 nhp = MPLS_LIST_HEAD(&g->nexthop);
1247 while (nhp != NULL) {
1248 if (nhp->index > nh->index) {
1249 MPLS_LIST_INSERT_BEFORE(&g->nexthop, nhp, nh, _global);
1250 return;
1252 nhp = MPLS_LIST_NEXT(&g->nexthop, nhp, _global);
1254 MPLS_LIST_ADD_TAIL(&g->nexthop, nh, _global, ldp_nexthop);
1257 void _ldp_global_del_nexthop(ldp_global * g, ldp_nexthop * nh)
1259 MPLS_ASSERT(g && nh);
1260 MPLS_LIST_REMOVE(&g->nexthop, nh, _global);