We no longer need _ldp_global_ifmgr_callback because
[mpls-ldp-portable.git] / ldp / ldp_global.c
blob8baea0c8d22d99e8e3a4070d79542d7fb4c21c8f
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 #if 0
225 mpls_if_handle iff;
226 mpls_inet_addr addr;
227 mpls_return_enum retval;
229 retval = mpls_ifmgr_getfirst_address(g->ifmgr_handle, &iff, &addr);
230 if (retval == MPLS_FATAL) {
231 goto ldp_global_startup_cleanup;
233 if (retval == MPLS_SUCCESS) {
234 do {
235 ldp_addr *a;
236 ldp_if *i;
237 if (!(a = ldp_addr_create(g, &addr))) {
238 goto ldp_global_startup_cleanup;
240 a->if_handle = iff;
241 if ((i = ldp_global_find_if_handle(g, iff))) {
242 ldp_if_add_addr(i, a);
244 } while (mpls_ifmgr_getnext_address(g->ifmgr_handle, &iff, &addr) ==
245 MPLS_SUCCESS);
249 mpls_fec fec;
250 mpls_nexthop nexthop;
251 mpls_return_enum retval;
253 retval = mpls_fib_getfirst_route(g->fib_handle, &fec, &nexthop);
254 if (retval == MPLS_FATAL) {
255 goto ldp_global_startup_cleanup;
257 if (retval == MPLS_SUCCESS) {
258 do {
259 ldp_nexthop *n;
260 ldp_fec *f;
262 if (!(f = ldp_fec_find(g, &fec))) {
263 f = ldp_fec_create(g, &fec);
264 if (!f) {
265 goto ldp_global_startup_cleanup;
269 n = ldp_nexthop_create();
270 if (!n) {
271 goto ldp_global_startup_cleanup;
274 memcpy(&n->info, &nexthop, sizeof(mpls_nexthop));
275 if (ldp_fec_add_nexthop(g, f, n) != MPLS_SUCCESS) {
276 goto ldp_global_startup_cleanup;
278 _ldp_global_add_nexthop(g, n);
279 } while (mpls_fib_getnext_route(g->fib_handle, &fec, &nexthop) ==
280 MPLS_SUCCESS);
283 #endif
285 e = MPLS_LIST_HEAD(&g->entity);
286 while (e != NULL) {
287 ldp_entity_startup(g, e);
288 e = MPLS_LIST_NEXT(&g->entity, e, _global);
291 g->admin_state = MPLS_ADMIN_ENABLE;
293 LDP_EXIT(g->user_data, "ldp_global_startup");
294 return MPLS_SUCCESS;
296 ldp_global_startup_cleanup:
297 ldp_global_shutdown(g);
298 mpls_socket_close(g->socket_handle, g->hello_socket);
299 mpls_socket_close(g->socket_handle, g->listen_socket);
300 g->hello_socket = 0;
301 g->listen_socket = 0;
303 LDP_EXIT(g->user_data, "ldp_global_startup-error");
305 return MPLS_FAILURE;
308 mpls_return_enum ldp_global_shutdown(ldp_global * g)
310 ldp_entity *e = NULL;
311 ldp_nexthop *n;
312 ldp_fec *f;
313 ldp_addr *a;
314 ldp_if *i;
316 MPLS_ASSERT(g);
318 LDP_ENTER(g->user_data, "ldp_global_shutdown");
320 e = MPLS_LIST_HEAD(&g->entity);
321 while (e != NULL) {
322 ldp_entity_shutdown(g, e, 1);
323 e = MPLS_LIST_NEXT(&g->entity, e, _global);
326 g->admin_state = MPLS_ADMIN_DISABLE;
328 while ((f = MPLS_LIST_HEAD(&g->fec))) {
329 while ((n = MPLS_LIST_HEAD(&f->nh_root))) {
330 ldp_fec_del_nexthop(g, f, n);
332 MPLS_REFCNT_RELEASE2(g, f, ldp_fec_delete);
335 while ((i = MPLS_LIST_HEAD(&g->iff))) {
336 while ((a = MPLS_LIST_HEAD(&i->addr_root))) {
337 ldp_if_del_addr(g, i, a);
339 MPLS_REFCNT_RELEASE2(g, i, ldp_if_delete);
342 mpls_socket_readlist_del(g->socket_handle, g->hello_socket);
343 mpls_socket_close(g->socket_handle, g->hello_socket);
345 mpls_socket_readlist_del(g->socket_handle, g->listen_socket);
346 mpls_socket_close(g->socket_handle, g->listen_socket);
348 mpls_lock_release(g->global_lock);
349 mpls_timer_close(g->timer_handle);
350 mpls_lock_get(g->global_lock);
352 mpls_socket_mgr_close(g->socket_handle);
353 mpls_ifmgr_close(g->ifmgr_handle);
354 mpls_fib_close(g->fib_handle);
356 #if MPLS_USE_LSR
357 #else
358 mpls_mpls_close(g->mpls_handle);
359 #endif
361 LDP_EXIT(g->user_data, "ldp_global_shutdown");
363 return MPLS_SUCCESS;
366 mpls_return_enum ldp_global_delete(ldp_global * g)
368 if (g) {
369 mpls_tree_delete(g->addr_tree);
370 mpls_tree_delete(g->fec_tree);
372 mpls_lock_delete(g->global_lock);
373 LDP_PRINT(g->user_data, "global delete\n");
374 mpls_free(g);
376 return MPLS_SUCCESS;
379 void _ldp_global_add_attr(ldp_global * g, ldp_attr * a)
381 ldp_attr *ap = NULL;
383 MPLS_ASSERT(g && a);
384 MPLS_REFCNT_HOLD(a);
385 ap = MPLS_LIST_HEAD(&g->attr);
386 while (ap != NULL) {
387 if (ap->index > a->index) {
388 MPLS_LIST_INSERT_BEFORE(&g->attr, ap, a, _global);
389 return;
391 ap = MPLS_LIST_NEXT(&g->attr, ap, _global);
393 MPLS_LIST_ADD_TAIL(&g->attr, a, _global, ldp_attr);
396 void _ldp_global_del_attr(ldp_global * g, ldp_attr * a)
398 MPLS_ASSERT(g && a);
399 MPLS_LIST_REMOVE(&g->attr, a, _global);
400 MPLS_REFCNT_RELEASE(a, ldp_attr_delete);
403 void _ldp_global_add_peer(ldp_global * g, ldp_peer * p)
405 ldp_peer *pp = NULL;
407 MPLS_ASSERT(g && p);
408 MPLS_REFCNT_HOLD(p);
409 pp = MPLS_LIST_HEAD(&g->peer);
410 while (pp != NULL) {
411 if (pp->index > p->index) {
412 MPLS_LIST_INSERT_BEFORE(&g->peer, pp, p, _global);
413 return;
415 pp = MPLS_LIST_NEXT(&g->peer, pp, _global);
417 MPLS_LIST_ADD_TAIL(&g->peer, p, _global, ldp_peer);
420 void _ldp_global_del_peer(ldp_global * g, ldp_peer * p)
422 MPLS_ASSERT(g && p);
423 MPLS_LIST_REMOVE(&g->peer, p, _global);
424 MPLS_REFCNT_RELEASE(p, ldp_peer_delete);
428 * _ldp_global_add_if/del_if and _ldp_global_add_addr/del_addr are
429 * not the same as the rest of the global_add/del functions. They
430 * do not hold refcnts, they are used as part of the create and delete
431 * process of these structures
434 void _ldp_global_add_if(ldp_global * g, ldp_if * i)
436 ldp_if *ip = NULL;
438 MPLS_ASSERT(g && i);
439 ip = MPLS_LIST_HEAD(&g->iff);
440 while (ip != NULL) {
441 if (ip->index > i->index) {
442 MPLS_LIST_INSERT_BEFORE(&g->iff, ip, i, _global);
443 return;
445 ip = MPLS_LIST_NEXT(&g->iff, ip, _global);
447 MPLS_LIST_ADD_TAIL(&g->iff, i, _global, ldp_if);
450 void _ldp_global_del_if(ldp_global * g, ldp_if * i)
452 MPLS_ASSERT(g && i);
453 MPLS_LIST_REMOVE(&g->iff, i, _global);
456 void _ldp_global_add_addr(ldp_global * g, ldp_addr * a)
458 ldp_addr *ap = NULL;
460 MPLS_ASSERT(g && a);
461 ap = MPLS_LIST_HEAD(&g->addr);
462 while (ap != NULL) {
463 if (ap->index > a->index) {
464 MPLS_LIST_INSERT_BEFORE(&g->addr, ap, a, _global);
465 return;
467 ap = MPLS_LIST_NEXT(&g->addr, ap, _global);
469 MPLS_LIST_ADD_TAIL(&g->addr, a, _global, ldp_addr);
472 void _ldp_global_del_addr(ldp_global * g, ldp_addr * a)
474 MPLS_ASSERT(g && a);
475 MPLS_LIST_REMOVE(&g->addr, a, _global);
480 void _ldp_global_add_adj(ldp_global * g, ldp_adj * a)
482 ldp_adj *ap = NULL;
484 MPLS_ASSERT(g && a);
485 MPLS_REFCNT_HOLD(a);
486 ap = MPLS_LIST_HEAD(&g->adj);
487 while (ap != NULL) {
488 if (ap->index > a->index) {
489 MPLS_LIST_INSERT_BEFORE(&g->adj, ap, a, _global);
490 return;
492 ap = MPLS_LIST_NEXT(&g->adj, ap, _global);
494 MPLS_LIST_ADD_TAIL(&g->adj, a, _global, ldp_adj);
497 void _ldp_global_del_adj(ldp_global * g, ldp_adj * a)
499 MPLS_ASSERT(g && a);
500 MPLS_LIST_REMOVE(&g->adj, a, _global);
501 MPLS_REFCNT_RELEASE(a, ldp_adj_delete);
504 void _ldp_global_add_entity(ldp_global * g, ldp_entity * e)
506 ldp_entity *ep = NULL;
508 MPLS_ASSERT(g && e);
509 MPLS_REFCNT_HOLD(e);
510 ep = MPLS_LIST_HEAD(&g->entity);
511 while (ep != NULL) {
512 if (ep->index > e->index) {
513 MPLS_LIST_INSERT_BEFORE(&g->entity, ep, e, _global);
514 return;
516 ep = MPLS_LIST_NEXT(&g->entity, ep, _global);
518 MPLS_LIST_ADD_TAIL(&g->entity, e, _global, ldp_entity);
521 void _ldp_global_del_entity(ldp_global * g, ldp_entity * e)
523 MPLS_ASSERT(g && e);
524 MPLS_LIST_REMOVE(&g->entity, e, _global);
525 MPLS_REFCNT_RELEASE(e, ldp_entity_delete);
528 void _ldp_global_add_session(ldp_global * g, ldp_session * s)
530 ldp_session *sp = NULL;
532 MPLS_ASSERT(g && s);
533 MPLS_REFCNT_HOLD(s);
534 s->on_global = MPLS_BOOL_TRUE;
535 sp = MPLS_LIST_HEAD(&g->session);
536 while (sp != NULL) {
537 if (sp->index > s->index) {
538 MPLS_LIST_INSERT_BEFORE(&g->session, sp, s, _global);
539 return;
541 sp = MPLS_LIST_NEXT(&g->session, sp, _global);
543 MPLS_LIST_ADD_TAIL(&g->session, s, _global, ldp_session);
546 void _ldp_global_del_session(ldp_global * g, ldp_session * s)
548 MPLS_ASSERT(g && s);
549 MPLS_ASSERT(s->on_global == MPLS_BOOL_TRUE);
550 MPLS_LIST_REMOVE(&g->session, s, _global);
551 s->on_global = MPLS_BOOL_FALSE;
552 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
555 mpls_return_enum _ldp_global_add_inlabel(ldp_global * g, ldp_inlabel * i)
557 ldp_inlabel *ip = NULL;
558 mpls_return_enum result;
560 MPLS_ASSERT(g && i);
562 #if MPLS_USE_LSR
564 lsr_insegment iseg;
565 memcpy(&iseg.info,&i->info,sizeof(mpls_insegment));
566 result = lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_ADD|
567 LSR_INSEGMENT_CFG_NPOP|LSR_INSEGMENT_CFG_FAMILY|
568 LSR_INSEGMENT_CFG_LABELSPACE|LSR_INSEGMENT_CFG_LABEL|
569 LSR_INSEGMENT_CFG_OWNER);
570 memcpy(&i->info, &iseg.info, sizeof(mpls_insegment));
571 i->info.handle = iseg.index;
573 #else
574 result = mpls_mpls_insegment_add(g->mpls_handle, &i->info);
575 #endif
576 if (result != MPLS_SUCCESS) {
577 return result;
580 MPLS_REFCNT_HOLD(i);
581 ip = MPLS_LIST_HEAD(&g->inlabel);
582 while (ip != NULL) {
583 if (ip->index > i->index) {
584 MPLS_LIST_INSERT_BEFORE(&g->inlabel, ip, i, _global);
585 return MPLS_SUCCESS;
587 ip = MPLS_LIST_NEXT(&g->inlabel, ip, _global);
589 MPLS_LIST_ADD_TAIL(&g->inlabel, i, _global, ldp_inlabel);
590 return MPLS_SUCCESS;
593 mpls_return_enum _ldp_global_del_inlabel(ldp_global * g, ldp_inlabel * i)
595 MPLS_ASSERT(g && i);
596 MPLS_ASSERT(i->reuse_count == 0);
597 #if MPLS_USE_LSR
599 lsr_insegment iseg;
600 iseg.index = i->info.handle;
601 lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_DEL);
603 #else
604 mpls_mpls_insegment_del(g->mpls_handle, &i->info);
605 #endif
606 MPLS_LIST_REMOVE(&g->inlabel, i, _global);
607 MPLS_REFCNT_RELEASE(i, ldp_inlabel_delete);
608 return MPLS_SUCCESS;
611 mpls_return_enum _ldp_global_add_outlabel(ldp_global * g, ldp_outlabel * o)
613 ldp_outlabel *op = NULL;
614 mpls_return_enum result;
616 MPLS_ASSERT(g && o);
617 #if MPLS_USE_LSR
619 lsr_outsegment oseg;
620 memcpy(&oseg.info, &o->info, sizeof(mpls_outsegment));
621 result = lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_ADD|
622 LSR_OUTSEGMENT_CFG_PUSH_LABEL|LSR_OUTSEGMENT_CFG_OWNER|
623 LSR_OUTSEGMENT_CFG_INTERFACE|LSR_OUTSEGMENT_CFG_LABEL|
624 LSR_OUTSEGMENT_CFG_NEXTHOP);
625 o->info.handle = oseg.index;
627 #else
628 result = mpls_mpls_outsegment_add(g->mpls_handle, &o->info);
629 #endif
631 if (result != MPLS_SUCCESS) {
632 return result;
635 MPLS_REFCNT_HOLD(o);
636 o->switching = MPLS_BOOL_TRUE;
637 op = MPLS_LIST_HEAD(&g->outlabel);
638 while (op != NULL) {
639 if (op->index > o->index) {
640 MPLS_LIST_INSERT_BEFORE(&g->outlabel, op, o, _global);
641 return MPLS_SUCCESS;
643 op = MPLS_LIST_NEXT(&g->outlabel, op, _global);
645 MPLS_LIST_ADD_TAIL(&g->outlabel, o, _global, ldp_outlabel);
646 return MPLS_SUCCESS;
649 mpls_return_enum _ldp_global_del_outlabel(ldp_global * g, ldp_outlabel * o)
651 MPLS_ASSERT(g && o);
652 #if MPLS_USE_LSR
654 lsr_outsegment oseg;
655 oseg.index = o->info.handle;
656 lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_DEL);
658 #else
659 mpls_mpls_outsegment_del(g->mpls_handle, &o->info);
660 #endif
662 o->switching = MPLS_BOOL_FALSE;
663 MPLS_ASSERT(o->merge_count == 0);
664 MPLS_LIST_REMOVE(&g->outlabel, o, _global);
665 MPLS_REFCNT_RELEASE(o, ldp_outlabel_delete);
666 return MPLS_SUCCESS;
669 mpls_return_enum ldp_global_find_attr_index(ldp_global * g, uint32_t index,
670 ldp_attr ** attr)
672 ldp_attr *a = NULL;
674 if (g && index > 0) {
676 /* because we sort our inserts by index, this lets us know
677 if we've "walked" past the end of the list */
679 a = MPLS_LIST_TAIL(&g->attr);
680 if (a == NULL || a->index < index) {
681 return MPLS_END_OF_LIST;
682 *attr = NULL;
685 a = MPLS_LIST_HEAD(&g->attr);
686 while (a != NULL) {
687 if (a->index == index) {
688 *attr = a;
689 return MPLS_SUCCESS;
691 a = MPLS_LIST_NEXT(&g->attr, a, _global);
694 *attr = NULL;
695 return MPLS_FAILURE;
698 mpls_return_enum ldp_global_find_session_index(ldp_global * g, uint32_t index,
699 ldp_session ** session)
701 ldp_session *s = NULL;
703 if (g && index > 0) {
705 /* because we sort our inserts by index, this lets us know
706 if we've "walked" past the end of the list */
708 s = MPLS_LIST_TAIL(&g->session);
709 if (s == NULL || s->index < index) {
710 *session = NULL;
711 return MPLS_END_OF_LIST;
714 s = MPLS_LIST_HEAD(&g->session);
715 while (s != NULL) {
716 if (s->index == index) {
717 *session = s;
718 return MPLS_SUCCESS;
720 s = MPLS_LIST_NEXT(&g->session, s, _global);
723 *session = NULL;
724 return MPLS_FAILURE;
727 mpls_return_enum ldp_global_find_inlabel_index(ldp_global * g, uint32_t index,
728 ldp_inlabel ** inlabel)
730 ldp_inlabel *i = NULL;
732 if (g && index > 0) {
734 /* because we sort our inserts by index, this lets us know
735 if we've "walked" past the end of the list */
737 i = MPLS_LIST_TAIL(&g->inlabel);
738 if (i == NULL || i->index < index) {
739 *inlabel = NULL;
740 return MPLS_END_OF_LIST;
743 i = MPLS_LIST_HEAD(&g->inlabel);
744 while (i != NULL) {
745 if (i->index == index) {
746 *inlabel = i;
747 return MPLS_SUCCESS;
749 i = MPLS_LIST_NEXT(&g->inlabel, i, _global);
752 *inlabel = NULL;
753 return MPLS_FAILURE;
756 mpls_return_enum ldp_global_find_outlabel_index(ldp_global * g, uint32_t index,
757 ldp_outlabel ** outlabel)
759 ldp_outlabel *o = NULL;
761 if (g && index > 0) {
763 /* because we sort our inserts by index, this lets us know
764 if we've "walked" past the end of the list */
766 o = MPLS_LIST_TAIL(&g->outlabel);
767 if (o == NULL || o->index < index) {
768 *outlabel = NULL;
769 return MPLS_END_OF_LIST;
772 o = MPLS_LIST_HEAD(&g->outlabel);
773 while (o != NULL) {
774 if (o->index == index) {
775 *outlabel = o;
776 return MPLS_SUCCESS;
778 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
781 *outlabel = NULL;
782 return MPLS_FAILURE;
785 ldp_outlabel *ldp_global_find_outlabel_handle(ldp_global * g,
786 mpls_outsegment_handle handle)
788 ldp_outlabel *o = MPLS_LIST_HEAD(&g->outlabel);
790 if (g) {
791 while (o != NULL) {
792 if (!mpls_outsegment_handle_compare(o->info.handle, handle))
793 return o;
795 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
798 return NULL;
801 mpls_return_enum ldp_global_find_entity_index(ldp_global * g, uint32_t index,
802 ldp_entity ** entity)
804 ldp_entity *e = NULL;
806 if (g && index > 0) {
808 /* because we sort our inserts by index, this lets us know
809 if we've "walked" past the end of the list */
811 e = MPLS_LIST_TAIL(&g->entity);
812 if (e == NULL || e->index < index) {
813 *entity = NULL;
814 return MPLS_END_OF_LIST;
817 e = MPLS_LIST_HEAD(&g->entity);
818 while (e != NULL) {
819 if (e->index == index) {
820 *entity = e;
821 return MPLS_SUCCESS;
823 e = MPLS_LIST_NEXT(&g->entity, e, _global);
826 *entity = NULL;
827 return MPLS_FAILURE;
830 ldp_peer *ldp_global_find_peer_addr(ldp_global * g, mpls_inet_addr * addr)
832 ldp_peer *p;
834 MPLS_ASSERT(g && addr);
836 /* JLEU: we will need to add a tree to optimize this search,
837 known peers will be in tree, unknown will take a "slow path" to
838 verify them, then be added to tree */
840 p = MPLS_LIST_HEAD(&g->peer);
841 while (p) {
842 LDP_PRINT(g->user_data,
843 "ldp_global_find_peer_lsrid: peer: %08x lsrid: %08x\n",
844 p->dest.addr.u.ipv4, addr->u.ipv4);
845 if (!mpls_inet_addr_compare(&p->dest.addr, addr)) {
846 return p;
848 p = MPLS_LIST_NEXT(&g->peer, p, _global);
850 return NULL;
853 mpls_return_enum ldp_global_find_adj_index(ldp_global * g, uint32_t index,
854 ldp_adj ** adj)
856 ldp_adj *a = NULL;
858 if (g && index > 0) {
859 /* because we sort our inserts by index, this lets us know
860 if we've "walked" past the end of the list */
862 a = MPLS_LIST_TAIL(&g->adj);
863 if (a == NULL || a->index < index) {
864 return MPLS_END_OF_LIST;
865 *adj = NULL;
868 a = MPLS_LIST_HEAD(&g->adj);
869 while (a != NULL) {
870 if (a->index == index) {
871 *adj = a;
872 return MPLS_SUCCESS;
874 a = MPLS_LIST_NEXT(&g->adj, a, _global);
877 *adj = NULL;
878 return MPLS_FAILURE;
881 mpls_return_enum ldp_global_find_peer_index(ldp_global * g, uint32_t index,
882 ldp_peer ** peer)
884 ldp_peer *p = NULL;
886 if (g && index > 0) {
887 /* because we sort our inserts by index, this lets us know
888 if we've "walked" past the end of the list */
890 p = MPLS_LIST_TAIL(&g->peer);
891 if (p == NULL || p->index < index) {
892 *peer = NULL;
893 return MPLS_END_OF_LIST;
896 p = MPLS_LIST_HEAD(&g->peer);
897 while (p != NULL) {
898 if (p->index == index) {
899 *peer = p;
900 return MPLS_SUCCESS;
902 p = MPLS_LIST_NEXT(&g->peer, p, _global);
905 *peer = NULL;
906 return MPLS_FAILURE;
909 mpls_return_enum ldp_global_find_fec_index(ldp_global * g, uint32_t index,
910 ldp_fec ** fec)
912 ldp_fec *f = NULL;
914 if (g && index > 0) {
915 /* because we sort our inserts by index, this lets us know
916 if we've "walked" past the end of the list */
918 f = MPLS_LIST_TAIL(&g->fec);
919 if (f == NULL || f->index < index) {
920 *fec = NULL;
921 return MPLS_END_OF_LIST;
924 f = MPLS_LIST_HEAD(&g->fec);
925 while (f != NULL) {
926 if (f->index == index) {
927 *fec = f;
928 return MPLS_SUCCESS;
930 f = MPLS_LIST_NEXT(&g->fec, f, _global);
933 *fec = NULL;
934 return MPLS_FAILURE;
937 mpls_return_enum ldp_global_find_fec(ldp_global * g, mpls_fec * m,
938 ldp_fec ** fec)
940 ldp_fec *f = NULL;
942 MPLS_ASSERT(g && m);
944 f = MPLS_LIST_HEAD(&g->fec);
945 do {
946 if (!mpls_fec_compare(m, &f->info)) {
947 *fec = f;
948 return MPLS_SUCCESS;
950 } while((f = MPLS_LIST_NEXT(&g->fec, f, _global)));
951 *fec = NULL;
952 return MPLS_FAILURE;
955 mpls_return_enum ldp_global_find_addr_index(ldp_global * g, uint32_t index,
956 ldp_addr ** addr)
958 ldp_addr *a = NULL;
960 if (g && index > 0) {
962 /* because we sort our inserts by index, this lets us know
963 if we've "walked" past the end of the list */
965 a = MPLS_LIST_TAIL(&g->addr);
966 if (a == NULL || a->index < index) {
967 *addr = NULL;
968 return MPLS_END_OF_LIST;
971 a = MPLS_LIST_HEAD(&g->addr);
972 while (a != NULL) {
973 if (a->index == index) {
974 *addr = a;
975 return MPLS_SUCCESS;
977 a = MPLS_LIST_NEXT(&g->addr, a, _global);
980 *addr = NULL;
981 return MPLS_FAILURE;
984 mpls_return_enum ldp_global_find_if_index(ldp_global * g, uint32_t index,
985 ldp_if ** iff)
987 ldp_if *i = NULL;
989 if (g && index > 0) {
991 /* because we sort our inserts by index, this lets us know
992 if we've "walked" past the end of the list */
994 i = MPLS_LIST_TAIL(&g->iff);
995 if (i == NULL || i->index < index) {
996 *iff = NULL;
997 return MPLS_END_OF_LIST;
1000 i = MPLS_LIST_HEAD(&g->iff);
1001 while (i != NULL) {
1002 if (i->index == index) {
1003 *iff = i;
1004 return MPLS_SUCCESS;
1006 i = MPLS_LIST_NEXT(&g->iff, i, _global);
1009 *iff = NULL;
1010 return MPLS_FAILURE;
1013 ldp_if *ldp_global_find_if_handle(ldp_global * g, mpls_if_handle handle)
1015 ldp_if *i = MPLS_LIST_HEAD(&g->iff);
1017 if (g) {
1018 while (i != NULL) {
1019 if (!mpls_if_handle_compare(i->handle, handle))
1020 return i;
1022 i = MPLS_LIST_NEXT(&g->iff, i, _global);
1025 return NULL;
1028 ldp_adj *ldp_global_find_adj_ldpid(ldp_global * g, mpls_inet_addr * lsraddr,
1029 int labelspace)
1032 ldp_adj *a = MPLS_LIST_HEAD(&g->adj);
1034 while (a != NULL) {
1035 if ((!mpls_inet_addr_compare(lsraddr, &a->remote_lsr_address)) &&
1036 labelspace == a->remote_label_space)
1037 return a;
1039 a = MPLS_LIST_NEXT(&g->adj, a, _global);
1041 return NULL;
1044 mpls_return_enum ldp_global_find_tunnel_index(ldp_global * g, uint32_t index,
1045 ldp_tunnel ** tunnel)
1047 ldp_tunnel *t = NULL;
1049 if (g && index > 0) {
1050 /* because we sort our inserts by index, this lets us know
1051 if we've "walked" past the end of the list */
1053 t = MPLS_LIST_TAIL(&g->tunnel);
1054 if (t == NULL || t->index < index) {
1055 *tunnel = NULL;
1056 return MPLS_END_OF_LIST;
1059 t = MPLS_LIST_HEAD(&g->tunnel);
1060 while (t != NULL) {
1061 if (t->index == index) {
1062 *tunnel = t;
1063 return MPLS_SUCCESS;
1065 t = MPLS_LIST_NEXT(&g->tunnel, t, _global);
1068 *tunnel = NULL;
1069 return MPLS_FAILURE;
1072 mpls_return_enum ldp_global_find_resource_index(ldp_global * g, uint32_t index,
1073 ldp_resource ** resource)
1075 ldp_resource *r = NULL;
1077 if (g && index > 0) {
1078 /* because we sort our inserts by index, this lets us know
1079 if we've "walked" past the end of the list */
1081 r = MPLS_LIST_TAIL(&g->resource);
1082 if (r == NULL || r->index < index) {
1083 *resource = NULL;
1084 return MPLS_END_OF_LIST;
1087 r = MPLS_LIST_HEAD(&g->resource);
1088 while (r != NULL) {
1089 if (r->index == index) {
1090 *resource = r;
1091 return MPLS_SUCCESS;
1093 r = MPLS_LIST_NEXT(&g->resource, r, _global);
1096 *resource = NULL;
1097 return MPLS_FAILURE;
1100 mpls_return_enum ldp_global_find_hop_list_index(ldp_global * g, uint32_t index,
1101 ldp_hop_list ** hop_list)
1103 ldp_hop_list *h = NULL;
1105 if (g && index > 0) {
1106 /* because we sort our inserts by index, this lets us know
1107 if we've "walked" past the end of the list */
1109 h = MPLS_LIST_TAIL(&g->hop_list);
1110 if (h == NULL || h->index < index) {
1111 *hop_list = NULL;
1112 return MPLS_END_OF_LIST;
1115 h = MPLS_LIST_HEAD(&g->hop_list);
1116 while (h != NULL) {
1117 if (h->index == index) {
1118 *hop_list = h;
1119 return MPLS_SUCCESS;
1121 h = MPLS_LIST_NEXT(&g->hop_list, h, _global);
1124 *hop_list = NULL;
1125 return MPLS_FAILURE;
1128 void _ldp_global_add_tunnel(ldp_global * g, ldp_tunnel * t)
1130 ldp_tunnel *tp = NULL;
1132 MPLS_ASSERT(g && t);
1133 MPLS_REFCNT_HOLD(t);
1134 tp = MPLS_LIST_HEAD(&g->tunnel);
1135 while (tp != NULL) {
1136 if (tp->index > t->index) {
1137 MPLS_LIST_INSERT_BEFORE(&g->tunnel, tp, t, _global);
1138 return;
1140 tp = MPLS_LIST_NEXT(&g->tunnel, tp, _global);
1142 MPLS_LIST_ADD_TAIL(&g->tunnel, t, _global, ldp_tunnel);
1145 void _ldp_global_del_tunnel(ldp_global * g, ldp_tunnel * t)
1147 MPLS_ASSERT(g && t);
1148 MPLS_LIST_REMOVE(&g->tunnel, t, _global);
1149 MPLS_REFCNT_RELEASE(t, ldp_tunnel_delete);
1152 void _ldp_global_add_resource(ldp_global * g, ldp_resource * r)
1154 ldp_resource *rp = NULL;
1156 MPLS_ASSERT(g && r);
1157 MPLS_REFCNT_HOLD(r);
1158 rp = MPLS_LIST_HEAD(&g->resource);
1159 while (rp != NULL) {
1160 if (rp->index > r->index) {
1161 MPLS_LIST_INSERT_BEFORE(&g->resource, rp, r, _global);
1162 return;
1164 rp = MPLS_LIST_NEXT(&g->resource, rp, _global);
1166 MPLS_LIST_ADD_TAIL(&g->resource, r, _global, ldp_resource);
1169 void _ldp_global_del_resource(ldp_global * g, ldp_resource * r)
1171 MPLS_ASSERT(g && r);
1172 MPLS_LIST_REMOVE(&g->resource, r, _global);
1173 MPLS_REFCNT_RELEASE(r, ldp_resource_delete);
1176 void _ldp_global_add_hop_list(ldp_global * g, ldp_hop_list * h)
1178 ldp_hop_list *hp = NULL;
1180 MPLS_ASSERT(g && h);
1181 MPLS_REFCNT_HOLD(h);
1182 hp = MPLS_LIST_HEAD(&g->hop_list);
1183 while (hp != NULL) {
1184 if (hp->index > h->index) {
1185 MPLS_LIST_INSERT_BEFORE(&g->hop_list, hp, h, _global);
1186 return;
1188 hp = MPLS_LIST_NEXT(&g->hop_list, hp, _global);
1190 MPLS_LIST_ADD_TAIL(&g->hop_list, h, _global, ldp_hop_list);
1193 void _ldp_global_del_hop_list(ldp_global * g, ldp_hop_list * h)
1195 MPLS_ASSERT(g && h);
1196 MPLS_LIST_REMOVE(&g->hop_list, h, _global);
1197 MPLS_REFCNT_RELEASE(h, ldp_hop_list_delete);
1200 void _ldp_global_add_fec(ldp_global * g, ldp_fec * f)
1202 ldp_fec *fp = NULL;
1204 MPLS_ASSERT(g && f);
1206 * TESTING: jleu 6/7/2004, since I want the FEC to be cleaned up
1207 * when it no longer has a nexthop, addr, or label, the only things that
1208 * should increment the ref are those (nh, addr, label etc), not global
1209 * nor inserting into the tree. I also added this comment in
1210 * ldp_fec_create()
1211 MPLS_REFCNT_HOLD(f);
1213 fp = MPLS_LIST_HEAD(&g->fec);
1214 while (fp != NULL) {
1215 if (fp->index > f->index) {
1216 MPLS_LIST_INSERT_BEFORE(&g->fec, fp, f, _global);
1217 return;
1219 fp = MPLS_LIST_NEXT(&g->fec, fp, _global);
1221 MPLS_LIST_ADD_TAIL(&g->fec, f, _global, ldp_fec);
1224 void _ldp_global_del_fec(ldp_global * g, ldp_fec * f)
1226 MPLS_ASSERT(g && f);
1227 MPLS_LIST_REMOVE(&g->fec, f, _global);
1230 void _ldp_global_add_nexthop(ldp_global * g, ldp_nexthop * nh)
1232 ldp_nexthop *nhp = NULL;
1234 MPLS_ASSERT(g && nh);
1235 nhp = MPLS_LIST_HEAD(&g->nexthop);
1236 while (nhp != NULL) {
1237 if (nhp->index > nh->index) {
1238 MPLS_LIST_INSERT_BEFORE(&g->nexthop, nhp, nh, _global);
1239 return;
1241 nhp = MPLS_LIST_NEXT(&g->nexthop, nhp, _global);
1243 MPLS_LIST_ADD_TAIL(&g->nexthop, nh, _global, ldp_nexthop);
1246 void _ldp_global_del_nexthop(ldp_global * g, ldp_nexthop * nh)
1248 MPLS_ASSERT(g && nh);
1249 MPLS_LIST_REMOVE(&g->nexthop, nh, _global);