Updated label mapping to better support the new fec -> nh relationship
[mpls-ldp-portable.git] / ldp / ldp_global.c
blob269e633dc7d7a8217a0366d795e97da752c96e63
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 void _ldp_global_ifmgr_callback(mpls_cfg_handle handle, const mpls_update_enum type, mpls_inet_addr *addr)
52 ldp_session *s = NULL;
53 ldp_global *cfg = (ldp_global*)handle;
55 LDP_ENTER(cfg->user_data, "_ldp_global_ifmgr_callback");
57 mpls_lock_get(cfg->global_lock);
59 if (mpls_policy_address_export_check(cfg->user_data, addr) == MPLS_BOOL_TRUE) {
60 s = MPLS_LIST_HEAD(&cfg->session);
61 while (s != NULL) {
62 switch (type) {
63 case MPLS_UPDATE_ADD:
64 LDP_TRACE_LOG(cfg->user_data, MPLS_TRACE_STATE_ALL,
65 LDP_TRACE_FLAG_EVENT, "ADD\n");
66 ldp_addr_send(cfg, s, addr);
67 break;
68 case MPLS_UPDATE_DEL:
69 LDP_TRACE_LOG(cfg->user_data, MPLS_TRACE_STATE_ALL,
70 LDP_TRACE_FLAG_EVENT, "DEL\n");
71 ldp_waddr_send(cfg, s, addr);
72 break;
73 default:
74 MPLS_ASSERT(0);
76 s = MPLS_LIST_NEXT(&cfg->session, s, _global);
80 mpls_lock_release(cfg->global_lock);
82 LDP_EXIT(cfg->user_data, "_ldp_global_ifmgr_callback");
85 ldp_global *ldp_global_create(mpls_instance_handle data)
87 ldp_global *g = (ldp_global *) mpls_malloc(sizeof(ldp_global));
89 if (g) {
90 memset(g, 0, sizeof(ldp_global));
92 LDP_ENTER(g->user_data, "ldp_global_create");
94 g->global_lock = mpls_lock_create("_ldp_global_lock_");
95 mpls_lock_get(g->global_lock);
97 MPLS_LIST_INIT(&g->hop_list, ldp_hop_list);
98 MPLS_LIST_INIT(&g->outlabel, ldp_outlabel);
99 MPLS_LIST_INIT(&g->resource, ldp_resource);
100 MPLS_LIST_INIT(&g->inlabel, ldp_inlabel);
101 MPLS_LIST_INIT(&g->session, ldp_session);
102 MPLS_LIST_INIT(&g->nexthop, ldp_nexthop);
103 MPLS_LIST_INIT(&g->tunnel, ldp_tunnel);
104 MPLS_LIST_INIT(&g->entity, ldp_entity);
105 MPLS_LIST_INIT(&g->attr, ldp_attr);
106 MPLS_LIST_INIT(&g->peer, ldp_peer);
107 MPLS_LIST_INIT(&g->fec, ldp_fec);
108 MPLS_LIST_INIT(&g->adj, ldp_adj);
109 MPLS_LIST_INIT(&g->iff, ldp_if);
111 g->message_identifier = 1;
112 g->configuration_sequence_number = 1;
113 g->lsp_control_mode = LDP_GLOBAL_DEF_CONTROL_MODE;
114 g->label_retention_mode = LDP_GLOBAL_DEF_RETENTION_MODE;
115 g->lsp_repair_mode = LDP_GLOBAL_DEF_REPAIR_MODE;
116 g->propagate_release = LDP_GLOBAL_DEF_PROPOGATE_RELEASE;
117 g->label_merge = LDP_GLOBAL_DEF_LABEL_MERGE;
118 g->loop_detection_mode = LDP_GLOBAL_DEF_LOOP_DETECTION_MODE;
119 g->ttl_less_domain = LDP_GLOBAL_DEF_TTLLESS_DOMAIN;
120 g->local_tcp_port = LDP_GLOBAL_DEF_LOCAL_TCP_PORT;
121 g->local_udp_port = LDP_GLOBAL_DEF_LOCAL_UDP_PORT;
122 g->send_address_messages = LDP_GLOBAL_DEF_SEND_ADDR_MSG;
123 g->backoff_step = LDP_GLOBAL_DEF_BACKOFF_STEP;
124 g->send_lsrid_mapping = LDP_GLOBAL_DEF_SEND_LSRID_MAPPING;
125 g->no_route_to_peer_time = LDP_GLOBAL_DEF_NO_ROUTE_RETRY_TIME;
127 g->keepalive_timer = LDP_ENTITY_DEF_KEEPALIVE_TIMER;
128 g->keepalive_interval = LDP_ENTITY_DEF_KEEPALIVE_INTERVAL;
129 g->hellotime_timer = LDP_ENTITY_DEF_HELLOTIME_TIMER;
130 g->hellotime_interval = LDP_ENTITY_DEF_HELLOTIME_INTERVAL;
132 g->admin_state = MPLS_ADMIN_DISABLE;
133 g->user_data = data;
135 mpls_lock_release(g->global_lock);
137 LDP_EXIT(g->user_data, "ldp_global_create");
140 return g;
143 mpls_return_enum ldp_global_startup(ldp_global * g)
145 ldp_entity *e = NULL;
146 mpls_dest dest;
148 MPLS_ASSERT(g != NULL);
150 LDP_ENTER(g->user_data, "ldp_global_startup");
152 if (g->lsr_identifier.type == MPLS_FAMILY_NONE) {
153 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_ERROR,
154 "ldp_global_startup: invalid LSRID\n");
155 goto ldp_global_startup_cleanup;
158 g->timer_handle = mpls_timer_open(g->user_data);
159 if (mpls_timer_mgr_handle_verify(g->timer_handle) == MPLS_BOOL_FALSE) {
160 goto ldp_global_startup_cleanup;
163 g->socket_handle = mpls_socket_mgr_open(g->user_data);
164 if (mpls_socket_mgr_handle_verify(g->socket_handle) == MPLS_BOOL_FALSE) {
165 goto ldp_global_startup_cleanup;
168 g->ifmgr_handle = mpls_ifmgr_open(g->user_data, g, _ldp_global_ifmgr_callback);
169 if (mpls_ifmgr_handle_verify(g->ifmgr_handle) == MPLS_BOOL_FALSE) {
170 goto ldp_global_startup_cleanup;
173 g->fib_handle = mpls_fib_open(g->user_data, g);
174 if (mpls_fib_handle_verify(g->fib_handle) == MPLS_BOOL_FALSE) {
175 goto ldp_global_startup_cleanup;
178 #if MPLS_USE_LSR
179 if (!g->lsr_handle) {
180 goto ldp_global_startup_cleanup;
182 #else
183 g->mpls_handle = mpls_mpls_open(g->user_data);
184 if (mpls_mpls_handle_verify(g->mpls_handle) == MPLS_BOOL_FALSE) {
185 goto ldp_global_startup_cleanup;
187 #endif
189 g->addr_tree = mpls_tree_create(32);
190 g->fec_tree = mpls_tree_create(32);
192 g->hello_socket = mpls_socket_create_udp(g->socket_handle);
193 if (mpls_socket_handle_verify(g->socket_handle, g->hello_socket) == MPLS_BOOL_FALSE) {
194 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
195 "ldp_global_startup: error creating UDP socket\n");
196 goto ldp_global_startup_cleanup;
199 dest.addr.type = MPLS_FAMILY_IPV4;
200 dest.port = g->local_udp_port;
201 dest.addr.u.ipv4 = INADDR_ANY;
202 // dest.addr.u.ipv4 = INADDR_ALLRTRS_GROUP;
204 if (mpls_socket_bind(g->socket_handle, g->hello_socket, &dest) == MPLS_FAILURE) {
205 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
206 "ldp_global_startup: error binding UDP socket\n");
207 goto ldp_global_startup_cleanup;
210 if (mpls_socket_options(g->socket_handle, g->hello_socket,
211 MPLS_SOCKOP_NONBLOCK | MPLS_SOCKOP_REUSE) == MPLS_FAILURE) {
212 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
213 "ldp_global_startup: error setting UDP socket options\n");
214 goto ldp_global_startup_cleanup;
216 if (mpls_socket_multicast_options(g->socket_handle, g->hello_socket, 1, 0) ==
217 MPLS_FAILURE) {
218 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
219 "ldp_global_startup: error setting UDP socket multicast options\n");
220 goto ldp_global_startup_cleanup;
222 mpls_socket_readlist_add(g->socket_handle, g->hello_socket, 0, MPLS_SOCKET_UDP_DATA);
224 g->listen_socket = mpls_socket_create_tcp(g->socket_handle);
225 if (mpls_socket_handle_verify(g->socket_handle, g->listen_socket) == MPLS_BOOL_FALSE) {
226 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
227 "ldp_global_startup: error creating TCP socket\n");
228 goto ldp_global_startup_cleanup;
230 if (mpls_socket_options(g->socket_handle, g->listen_socket,
231 MPLS_SOCKOP_NONBLOCK | MPLS_SOCKOP_REUSE) == MPLS_FAILURE) {
232 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
233 "ldp_global_startup: error setting TCP socket options\n");
234 goto ldp_global_startup_cleanup;
237 dest.addr.type = MPLS_FAMILY_IPV4;
238 dest.port = g->local_tcp_port;
239 dest.addr.u.ipv4 = INADDR_ANY;
241 if (mpls_socket_bind(g->socket_handle, g->listen_socket, &dest) == MPLS_FAILURE) {
242 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
243 "ldp_global_startup: error binding TCP socket\n");
244 goto ldp_global_startup_cleanup;
247 if (mpls_socket_tcp_listen(g->socket_handle, g->listen_socket, 15) ==
248 MPLS_FAILURE) {
249 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
250 "ldp_global_startup: error setting listen buffer for TCP socket\n");
251 goto ldp_global_startup_cleanup;
254 mpls_socket_readlist_add(g->socket_handle, g->listen_socket, 0,
255 MPLS_SOCKET_TCP_LISTEN);
257 e = MPLS_LIST_HEAD(&g->entity);
258 while (e != NULL) {
259 ldp_entity_startup(g, e);
260 e = MPLS_LIST_NEXT(&g->entity, e, _global);
263 g->admin_state = MPLS_ADMIN_ENABLE;
265 LDP_EXIT(g->user_data, "ldp_global_startup");
266 return MPLS_SUCCESS;
268 ldp_global_startup_cleanup:
269 ldp_global_shutdown(g);
270 mpls_socket_close(g->socket_handle, g->hello_socket);
271 mpls_socket_close(g->socket_handle, g->listen_socket);
272 g->hello_socket = 0;
273 g->listen_socket = 0;
275 LDP_EXIT(g->user_data, "ldp_global_startup-error");
277 return MPLS_FAILURE;
280 mpls_return_enum ldp_global_shutdown(ldp_global * g)
282 ldp_entity *e = NULL;
284 MPLS_ASSERT(g);
286 LDP_ENTER(g->user_data, "ldp_global_shutdown");
288 e = MPLS_LIST_HEAD(&g->entity);
289 while (e != NULL) {
290 ldp_entity_shutdown(g, e, 1);
291 e = MPLS_LIST_NEXT(&g->entity, e, _global);
294 g->admin_state = MPLS_ADMIN_DISABLE;
296 mpls_socket_readlist_del(g->socket_handle, g->hello_socket);
297 mpls_socket_close(g->socket_handle, g->hello_socket);
299 mpls_socket_readlist_del(g->socket_handle, g->listen_socket);
300 mpls_socket_close(g->socket_handle, g->listen_socket);
302 mpls_tree_delete(g->addr_tree);
303 mpls_tree_delete(g->fec_tree);
305 mpls_lock_release(g->global_lock);
306 mpls_timer_close(g->timer_handle);
307 mpls_lock_get(g->global_lock);
309 mpls_socket_mgr_close(g->socket_handle);
310 mpls_ifmgr_close(g->ifmgr_handle);
311 mpls_fib_close(g->fib_handle);
313 #if MPLS_USE_LSR
314 #else
315 mpls_mpls_close(g->mpls_handle);
316 #endif
318 LDP_EXIT(g->user_data, "ldp_global_shutdown");
320 return MPLS_SUCCESS;
323 mpls_return_enum ldp_global_delete(ldp_global * g)
325 if (g) {
326 mpls_lock_delete(g->global_lock);
327 LDP_PRINT(g->user_data, "global delete\n");
328 mpls_free(g);
330 return MPLS_SUCCESS;
333 void _ldp_global_add_attr(ldp_global * g, ldp_attr * a)
335 ldp_attr *ap = NULL;
337 MPLS_ASSERT(g && a);
338 MPLS_REFCNT_HOLD(a);
339 ap = MPLS_LIST_HEAD(&g->attr);
340 while (ap != NULL) {
341 if (ap->index > a->index) {
342 MPLS_LIST_INSERT_BEFORE(&g->attr, ap, a, _global);
343 return;
345 ap = MPLS_LIST_NEXT(&g->attr, ap, _global);
347 MPLS_LIST_ADD_TAIL(&g->attr, a, _global, ldp_attr);
350 void _ldp_global_del_attr(ldp_global * g, ldp_attr * a)
352 MPLS_ASSERT(g && a);
353 MPLS_LIST_REMOVE(&g->attr, a, _global);
354 MPLS_REFCNT_RELEASE(a, ldp_attr_delete);
357 void _ldp_global_add_peer(ldp_global * g, ldp_peer * p)
359 ldp_peer *pp = NULL;
361 MPLS_ASSERT(g && p);
362 MPLS_REFCNT_HOLD(p);
363 pp = MPLS_LIST_HEAD(&g->peer);
364 while (pp != NULL) {
365 if (pp->index > p->index) {
366 MPLS_LIST_INSERT_BEFORE(&g->peer, pp, p, _global);
367 return;
369 pp = MPLS_LIST_NEXT(&g->peer, pp, _global);
371 MPLS_LIST_ADD_TAIL(&g->peer, p, _global, ldp_peer);
374 void _ldp_global_del_peer(ldp_global * g, ldp_peer * p)
376 MPLS_ASSERT(g && p);
377 MPLS_LIST_REMOVE(&g->peer, p, _global);
378 MPLS_REFCNT_RELEASE(p, ldp_peer_delete);
382 * _ldp_global_add_if/del_if and _ldp_global_add_addr/del_addr are
383 * not the same as the rest of the global_add/del functions. They
384 * do not hold refcnts, they are used as part of the create and delete
385 * process of these structures
388 void _ldp_global_add_if(ldp_global * g, ldp_if * i)
390 ldp_if *ip = NULL;
392 MPLS_ASSERT(g && i);
393 ip = MPLS_LIST_HEAD(&g->iff);
394 while (ip != NULL) {
395 if (ip->index > i->index) {
396 MPLS_LIST_INSERT_BEFORE(&g->iff, ip, i, _global);
397 return;
399 ip = MPLS_LIST_NEXT(&g->iff, ip, _global);
401 MPLS_LIST_ADD_TAIL(&g->iff, i, _global, ldp_if);
404 void _ldp_global_del_if(ldp_global * g, ldp_if * i)
406 MPLS_ASSERT(g && i);
407 MPLS_LIST_REMOVE(&g->iff, i, _global);
410 void _ldp_global_add_addr(ldp_global * g, ldp_addr * a)
412 ldp_addr *ap = NULL;
414 MPLS_ASSERT(g && a);
415 ap = MPLS_LIST_HEAD(&g->addr);
416 while (ap != NULL) {
417 if (ap->index > a->index) {
418 MPLS_LIST_INSERT_BEFORE(&g->addr, ap, a, _global);
419 return;
421 ap = MPLS_LIST_NEXT(&g->addr, ap, _global);
423 MPLS_LIST_ADD_TAIL(&g->addr, a, _global, ldp_addr);
426 void _ldp_global_del_addr(ldp_global * g, ldp_addr * a)
428 MPLS_ASSERT(g && a);
429 MPLS_LIST_REMOVE(&g->addr, a, _global);
434 void _ldp_global_add_adj(ldp_global * g, ldp_adj * a)
436 ldp_adj *ap = NULL;
438 MPLS_ASSERT(g && a);
439 MPLS_REFCNT_HOLD(a);
440 ap = MPLS_LIST_HEAD(&g->adj);
441 while (ap != NULL) {
442 if (ap->index > a->index) {
443 MPLS_LIST_INSERT_BEFORE(&g->adj, ap, a, _global);
444 return;
446 ap = MPLS_LIST_NEXT(&g->adj, ap, _global);
448 MPLS_LIST_ADD_TAIL(&g->adj, a, _global, ldp_adj);
451 void _ldp_global_del_adj(ldp_global * g, ldp_adj * a)
453 MPLS_ASSERT(g && a);
454 MPLS_LIST_REMOVE(&g->adj, a, _global);
455 MPLS_REFCNT_RELEASE(a, ldp_adj_delete);
458 void _ldp_global_add_entity(ldp_global * g, ldp_entity * e)
460 ldp_entity *ep = NULL;
462 MPLS_ASSERT(g && e);
463 MPLS_REFCNT_HOLD(e);
464 ep = MPLS_LIST_HEAD(&g->entity);
465 while (ep != NULL) {
466 if (ep->index > e->index) {
467 MPLS_LIST_INSERT_BEFORE(&g->entity, ep, e, _global);
468 return;
470 ep = MPLS_LIST_NEXT(&g->entity, ep, _global);
472 MPLS_LIST_ADD_TAIL(&g->entity, e, _global, ldp_entity);
475 void _ldp_global_del_entity(ldp_global * g, ldp_entity * e)
477 MPLS_ASSERT(g && e);
478 MPLS_LIST_REMOVE(&g->entity, e, _global);
479 MPLS_REFCNT_RELEASE(e, ldp_entity_delete);
482 void _ldp_global_add_session(ldp_global * g, ldp_session * s)
484 ldp_session *sp = NULL;
486 MPLS_ASSERT(g && s);
487 MPLS_REFCNT_HOLD(s);
488 s->on_global = MPLS_BOOL_TRUE;
489 sp = MPLS_LIST_HEAD(&g->session);
490 while (sp != NULL) {
491 if (sp->index > s->index) {
492 MPLS_LIST_INSERT_BEFORE(&g->session, sp, s, _global);
493 return;
495 sp = MPLS_LIST_NEXT(&g->session, sp, _global);
497 MPLS_LIST_ADD_TAIL(&g->session, s, _global, ldp_session);
500 void _ldp_global_del_session(ldp_global * g, ldp_session * s)
502 MPLS_ASSERT(g && s);
503 MPLS_ASSERT(s->on_global == MPLS_BOOL_TRUE);
504 MPLS_LIST_REMOVE(&g->session, s, _global);
505 s->on_global = MPLS_BOOL_FALSE;
506 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
509 mpls_return_enum _ldp_global_add_inlabel(ldp_global * g, ldp_inlabel * i)
511 ldp_inlabel *ip = NULL;
512 mpls_return_enum result;
514 MPLS_ASSERT(g && i);
516 #if MPLS_USE_LSR
518 lsr_insegment iseg;
519 memcpy(&iseg.info,&i->info,sizeof(mpls_insegment));
520 result = lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_ADD|
521 LSR_INSEGMENT_CFG_NPOP|LSR_INSEGMENT_CFG_FAMILY|
522 LSR_INSEGMENT_CFG_LABELSPACE|LSR_INSEGMENT_CFG_LABEL|
523 LSR_INSEGMENT_CFG_OWNER);
524 memcpy(&i->info, &iseg.info, sizeof(mpls_insegment));
525 i->info.handle = iseg.index;
527 #else
528 result = mpls_mpls_insegment_add(g->mpls_handle, &i->info);
529 #endif
530 if (result != MPLS_SUCCESS) {
531 return result;
534 MPLS_REFCNT_HOLD(i);
535 ip = MPLS_LIST_HEAD(&g->inlabel);
536 while (ip != NULL) {
537 if (ip->index > i->index) {
538 MPLS_LIST_INSERT_BEFORE(&g->inlabel, ip, i, _global);
539 return MPLS_SUCCESS;
541 ip = MPLS_LIST_NEXT(&g->inlabel, ip, _global);
543 MPLS_LIST_ADD_TAIL(&g->inlabel, i, _global, ldp_inlabel);
544 return MPLS_SUCCESS;
547 mpls_return_enum _ldp_global_del_inlabel(ldp_global * g, ldp_inlabel * i)
549 MPLS_ASSERT(g && i);
550 MPLS_ASSERT(i->reuse_count == 0);
551 #if MPLS_USE_LSR
553 lsr_insegment iseg;
554 iseg.index = i->info.handle;
555 lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_DEL);
557 #else
558 mpls_mpls_insegment_del(g->mpls_handle, &i->info);
559 #endif
560 MPLS_LIST_REMOVE(&g->inlabel, i, _global);
561 MPLS_REFCNT_RELEASE(i, ldp_inlabel_delete);
562 return MPLS_SUCCESS;
565 mpls_return_enum _ldp_global_add_outlabel(ldp_global * g, ldp_outlabel * o)
567 ldp_outlabel *op = NULL;
568 mpls_return_enum result;
570 MPLS_ASSERT(g && o);
571 #if MPLS_USE_LSR
573 lsr_outsegment oseg;
574 memcpy(&oseg.info, &o->info, sizeof(mpls_outsegment));
575 result = lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_ADD|
576 LSR_OUTSEGMENT_CFG_PUSH_LABEL|LSR_OUTSEGMENT_CFG_OWNER|
577 LSR_OUTSEGMENT_CFG_INTERFACE|LSR_OUTSEGMENT_CFG_LABEL|
578 LSR_OUTSEGMENT_CFG_NEXTHOP);
579 o->info.handle = oseg.index;
581 #else
582 result = mpls_mpls_outsegment_add(g->mpls_handle, &o->info);
583 #endif
585 if (result != MPLS_SUCCESS) {
586 return result;
589 MPLS_REFCNT_HOLD(o);
590 o->switching = MPLS_BOOL_TRUE;
591 op = MPLS_LIST_HEAD(&g->outlabel);
592 while (op != NULL) {
593 if (op->index > o->index) {
594 MPLS_LIST_INSERT_BEFORE(&g->outlabel, op, o, _global);
595 return MPLS_SUCCESS;
597 op = MPLS_LIST_NEXT(&g->outlabel, op, _global);
599 MPLS_LIST_ADD_TAIL(&g->outlabel, o, _global, ldp_outlabel);
600 return MPLS_SUCCESS;
603 mpls_return_enum _ldp_global_del_outlabel(ldp_global * g, ldp_outlabel * o)
605 MPLS_ASSERT(g && o);
606 #if MPLS_USE_LSR
608 lsr_outsegment oseg;
609 oseg.index = o->info.handle;
610 lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_DEL);
612 #else
613 mpls_mpls_outsegment_del(g->mpls_handle, &o->info);
614 #endif
616 o->switching = MPLS_BOOL_FALSE;
617 MPLS_ASSERT(o->merge_count == 0);
618 MPLS_LIST_REMOVE(&g->outlabel, o, _global);
619 MPLS_REFCNT_RELEASE(o, ldp_outlabel_delete);
620 return MPLS_SUCCESS;
623 mpls_return_enum ldp_global_find_attr_index(ldp_global * g, uint32_t index,
624 ldp_attr ** attr)
626 ldp_attr *a = NULL;
628 if (g && index > 0) {
630 /* because we sort our inserts by index, this lets us know
631 if we've "walked" past the end of the list */
633 a = MPLS_LIST_TAIL(&g->attr);
634 if (a == NULL || a->index < index) {
635 return MPLS_END_OF_LIST;
636 *attr = NULL;
639 a = MPLS_LIST_HEAD(&g->attr);
640 while (a != NULL) {
641 if (a->index == index) {
642 *attr = a;
643 return MPLS_SUCCESS;
645 a = MPLS_LIST_NEXT(&g->attr, a, _global);
648 *attr = NULL;
649 return MPLS_FAILURE;
652 mpls_return_enum ldp_global_find_session_index(ldp_global * g, uint32_t index,
653 ldp_session ** session)
655 ldp_session *s = NULL;
657 if (g && index > 0) {
659 /* because we sort our inserts by index, this lets us know
660 if we've "walked" past the end of the list */
662 s = MPLS_LIST_TAIL(&g->session);
663 if (s == NULL || s->index < index) {
664 *session = NULL;
665 return MPLS_END_OF_LIST;
668 s = MPLS_LIST_HEAD(&g->session);
669 while (s != NULL) {
670 if (s->index == index) {
671 *session = s;
672 return MPLS_SUCCESS;
674 s = MPLS_LIST_NEXT(&g->session, s, _global);
677 *session = NULL;
678 return MPLS_FAILURE;
681 mpls_return_enum ldp_global_find_inlabel_index(ldp_global * g, uint32_t index,
682 ldp_inlabel ** inlabel)
684 ldp_inlabel *i = NULL;
686 if (g && index > 0) {
688 /* because we sort our inserts by index, this lets us know
689 if we've "walked" past the end of the list */
691 i = MPLS_LIST_TAIL(&g->inlabel);
692 if (i == NULL || i->index < index) {
693 *inlabel = NULL;
694 return MPLS_END_OF_LIST;
697 i = MPLS_LIST_HEAD(&g->inlabel);
698 while (i != NULL) {
699 if (i->index == index) {
700 *inlabel = i;
701 return MPLS_SUCCESS;
703 i = MPLS_LIST_NEXT(&g->inlabel, i, _global);
706 *inlabel = NULL;
707 return MPLS_FAILURE;
710 mpls_return_enum ldp_global_find_outlabel_index(ldp_global * g, uint32_t index,
711 ldp_outlabel ** outlabel)
713 ldp_outlabel *o = NULL;
715 if (g && index > 0) {
717 /* because we sort our inserts by index, this lets us know
718 if we've "walked" past the end of the list */
720 o = MPLS_LIST_TAIL(&g->outlabel);
721 if (o == NULL || o->index < index) {
722 *outlabel = NULL;
723 return MPLS_END_OF_LIST;
726 o = MPLS_LIST_HEAD(&g->outlabel);
727 while (o != NULL) {
728 if (o->index == index) {
729 *outlabel = o;
730 return MPLS_SUCCESS;
732 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
735 *outlabel = NULL;
736 return MPLS_FAILURE;
739 ldp_outlabel *ldp_global_find_outlabel_handle(ldp_global * g,
740 mpls_outsegment_handle handle)
742 ldp_outlabel *o = MPLS_LIST_HEAD(&g->outlabel);
744 if (g) {
745 while (o != NULL) {
746 if (!mpls_outsegment_handle_compare(o->info.handle, handle))
747 return o;
749 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
752 return NULL;
755 mpls_return_enum ldp_global_find_entity_index(ldp_global * g, uint32_t index,
756 ldp_entity ** entity)
758 ldp_entity *e = NULL;
760 if (g && index > 0) {
762 /* because we sort our inserts by index, this lets us know
763 if we've "walked" past the end of the list */
765 e = MPLS_LIST_TAIL(&g->entity);
766 if (e == NULL || e->index < index) {
767 *entity = NULL;
768 return MPLS_END_OF_LIST;
771 e = MPLS_LIST_HEAD(&g->entity);
772 while (e != NULL) {
773 if (e->index == index) {
774 *entity = e;
775 return MPLS_SUCCESS;
777 e = MPLS_LIST_NEXT(&g->entity, e, _global);
780 *entity = NULL;
781 return MPLS_FAILURE;
784 ldp_peer *ldp_global_find_peer_addr(ldp_global * g, mpls_inet_addr * addr)
786 ldp_peer *p;
788 MPLS_ASSERT(g && addr);
790 /* JLEU: we will need to add a tree to optimize this search,
791 known peers will be in tree, unknown will take a "slow path" to
792 verify them, then be added to tree */
794 p = MPLS_LIST_HEAD(&g->peer);
795 while (p) {
796 LDP_PRINT(g->user_data,
797 "ldp_global_find_peer_lsrid: peer: %08x lsrid: %08x\n",
798 p->dest.addr.u.ipv4, addr->u.ipv4);
799 if (!mpls_inet_addr_compare(&p->dest.addr, addr)) {
800 return p;
802 p = MPLS_LIST_NEXT(&g->peer, p, _global);
804 return NULL;
807 mpls_return_enum ldp_global_find_adj_index(ldp_global * g, uint32_t index,
808 ldp_adj ** adj)
810 ldp_adj *a = NULL;
812 if (g && index > 0) {
813 /* because we sort our inserts by index, this lets us know
814 if we've "walked" past the end of the list */
816 a = MPLS_LIST_TAIL(&g->adj);
817 if (a == NULL || a->index < index) {
818 return MPLS_END_OF_LIST;
819 *adj = NULL;
822 a = MPLS_LIST_HEAD(&g->adj);
823 while (a != NULL) {
824 if (a->index == index) {
825 *adj = a;
826 return MPLS_SUCCESS;
828 a = MPLS_LIST_NEXT(&g->adj, a, _global);
831 *adj = NULL;
832 return MPLS_FAILURE;
835 mpls_return_enum ldp_global_find_peer_index(ldp_global * g, uint32_t index,
836 ldp_peer ** peer)
838 ldp_peer *p = NULL;
840 if (g && index > 0) {
841 /* because we sort our inserts by index, this lets us know
842 if we've "walked" past the end of the list */
844 p = MPLS_LIST_TAIL(&g->peer);
845 if (p == NULL || p->index < index) {
846 *peer = NULL;
847 return MPLS_END_OF_LIST;
850 p = MPLS_LIST_HEAD(&g->peer);
851 while (p != NULL) {
852 if (p->index == index) {
853 *peer = p;
854 return MPLS_SUCCESS;
856 p = MPLS_LIST_NEXT(&g->peer, p, _global);
859 *peer = NULL;
860 return MPLS_FAILURE;
863 mpls_return_enum ldp_global_find_fec_index(ldp_global * g, uint32_t index,
864 ldp_fec ** fec)
866 ldp_fec *f = NULL;
868 if (g && index > 0) {
869 /* because we sort our inserts by index, this lets us know
870 if we've "walked" past the end of the list */
872 f = MPLS_LIST_TAIL(&g->fec);
873 if (f == NULL || f->index < index) {
874 *fec = NULL;
875 return MPLS_END_OF_LIST;
878 f = MPLS_LIST_HEAD(&g->fec);
879 while (f != NULL) {
880 if (f->index == index) {
881 *fec = f;
882 return MPLS_SUCCESS;
884 f = MPLS_LIST_NEXT(&g->fec, f, _global);
887 *fec = NULL;
888 return MPLS_FAILURE;
891 mpls_return_enum ldp_global_find_fec(ldp_global * g, mpls_fec * m,
892 ldp_fec ** fec)
894 ldp_fec *f = NULL;
896 MPLS_ASSERT(g && m);
898 f = MPLS_LIST_HEAD(&g->fec);
899 do {
900 if (!mpls_fec_compare(m, &f->info)) {
901 *fec = f;
902 return MPLS_SUCCESS;
904 } while((f = MPLS_LIST_NEXT(&g->fec, f, _global)));
905 *fec = NULL;
906 return MPLS_FAILURE;
909 mpls_return_enum ldp_global_find_if_index(ldp_global * g, uint32_t index,
910 ldp_if ** iff)
912 ldp_if *i = NULL;
914 if (g && index > 0) {
916 /* because we sort our inserts by index, this lets us know
917 if we've "walked" past the end of the list */
919 i = MPLS_LIST_TAIL(&g->iff);
920 if (i == NULL || i->index < index) {
921 *iff = NULL;
922 return MPLS_END_OF_LIST;
925 i = MPLS_LIST_HEAD(&g->iff);
926 while (i != NULL) {
927 if (i->index == index) {
928 *iff = i;
929 return MPLS_SUCCESS;
931 i = MPLS_LIST_NEXT(&g->iff, i, _global);
934 *iff = NULL;
935 return MPLS_FAILURE;
938 ldp_if *ldp_global_find_if_handle(ldp_global * g, mpls_if_handle handle)
940 ldp_if *i = MPLS_LIST_HEAD(&g->iff);
942 if (g) {
943 while (i != NULL) {
944 if (!mpls_if_handle_compare(i->handle, handle))
945 return i;
947 i = MPLS_LIST_NEXT(&g->iff, i, _global);
950 return NULL;
953 ldp_adj *ldp_global_find_adj_ldpid(ldp_global * g, mpls_inet_addr * lsraddr,
954 int labelspace)
957 ldp_adj *a = MPLS_LIST_HEAD(&g->adj);
959 while (a != NULL) {
960 if ((!mpls_inet_addr_compare(lsraddr, &a->remote_lsr_address)) &&
961 labelspace == a->remote_label_space)
962 return a;
964 a = MPLS_LIST_NEXT(&g->adj, a, _global);
966 return NULL;
969 mpls_return_enum ldp_global_find_tunnel_index(ldp_global * g, uint32_t index,
970 ldp_tunnel ** tunnel)
972 ldp_tunnel *t = NULL;
974 if (g && index > 0) {
975 /* because we sort our inserts by index, this lets us know
976 if we've "walked" past the end of the list */
978 t = MPLS_LIST_TAIL(&g->tunnel);
979 if (t == NULL || t->index < index) {
980 *tunnel = NULL;
981 return MPLS_END_OF_LIST;
984 t = MPLS_LIST_HEAD(&g->tunnel);
985 while (t != NULL) {
986 if (t->index == index) {
987 *tunnel = t;
988 return MPLS_SUCCESS;
990 t = MPLS_LIST_NEXT(&g->tunnel, t, _global);
993 *tunnel = NULL;
994 return MPLS_FAILURE;
997 mpls_return_enum ldp_global_find_resource_index(ldp_global * g, uint32_t index,
998 ldp_resource ** resource)
1000 ldp_resource *r = NULL;
1002 if (g && index > 0) {
1003 /* because we sort our inserts by index, this lets us know
1004 if we've "walked" past the end of the list */
1006 r = MPLS_LIST_TAIL(&g->resource);
1007 if (r == NULL || r->index < index) {
1008 *resource = NULL;
1009 return MPLS_END_OF_LIST;
1012 r = MPLS_LIST_HEAD(&g->resource);
1013 while (r != NULL) {
1014 if (r->index == index) {
1015 *resource = r;
1016 return MPLS_SUCCESS;
1018 r = MPLS_LIST_NEXT(&g->resource, r, _global);
1021 *resource = NULL;
1022 return MPLS_FAILURE;
1025 mpls_return_enum ldp_global_find_hop_list_index(ldp_global * g, uint32_t index,
1026 ldp_hop_list ** hop_list)
1028 ldp_hop_list *h = NULL;
1030 if (g && index > 0) {
1031 /* because we sort our inserts by index, this lets us know
1032 if we've "walked" past the end of the list */
1034 h = MPLS_LIST_TAIL(&g->hop_list);
1035 if (h == NULL || h->index < index) {
1036 *hop_list = NULL;
1037 return MPLS_END_OF_LIST;
1040 h = MPLS_LIST_HEAD(&g->hop_list);
1041 while (h != NULL) {
1042 if (h->index == index) {
1043 *hop_list = h;
1044 return MPLS_SUCCESS;
1046 h = MPLS_LIST_NEXT(&g->hop_list, h, _global);
1049 *hop_list = NULL;
1050 return MPLS_FAILURE;
1053 void _ldp_global_add_tunnel(ldp_global * g, ldp_tunnel * t)
1055 ldp_tunnel *tp = NULL;
1057 MPLS_ASSERT(g && t);
1058 MPLS_REFCNT_HOLD(t);
1059 tp = MPLS_LIST_HEAD(&g->tunnel);
1060 while (tp != NULL) {
1061 if (tp->index > t->index) {
1062 MPLS_LIST_INSERT_BEFORE(&g->tunnel, tp, t, _global);
1063 return;
1065 tp = MPLS_LIST_NEXT(&g->tunnel, tp, _global);
1067 MPLS_LIST_ADD_TAIL(&g->tunnel, t, _global, ldp_tunnel);
1070 void _ldp_global_del_tunnel(ldp_global * g, ldp_tunnel * t)
1072 MPLS_ASSERT(g && t);
1073 MPLS_LIST_REMOVE(&g->tunnel, t, _global);
1074 MPLS_REFCNT_RELEASE(t, ldp_tunnel_delete);
1077 void _ldp_global_add_resource(ldp_global * g, ldp_resource * r)
1079 ldp_resource *rp = NULL;
1081 MPLS_ASSERT(g && r);
1082 MPLS_REFCNT_HOLD(r);
1083 rp = MPLS_LIST_HEAD(&g->resource);
1084 while (rp != NULL) {
1085 if (rp->index > r->index) {
1086 MPLS_LIST_INSERT_BEFORE(&g->resource, rp, r, _global);
1087 return;
1089 rp = MPLS_LIST_NEXT(&g->resource, rp, _global);
1091 MPLS_LIST_ADD_TAIL(&g->resource, r, _global, ldp_resource);
1094 void _ldp_global_del_resource(ldp_global * g, ldp_resource * r)
1096 MPLS_ASSERT(g && r);
1097 MPLS_LIST_REMOVE(&g->resource, r, _global);
1098 MPLS_REFCNT_RELEASE(r, ldp_resource_delete);
1101 void _ldp_global_add_hop_list(ldp_global * g, ldp_hop_list * h)
1103 ldp_hop_list *hp = NULL;
1105 MPLS_ASSERT(g && h);
1106 MPLS_REFCNT_HOLD(h);
1107 hp = MPLS_LIST_HEAD(&g->hop_list);
1108 while (hp != NULL) {
1109 if (hp->index > h->index) {
1110 MPLS_LIST_INSERT_BEFORE(&g->hop_list, hp, h, _global);
1111 return;
1113 hp = MPLS_LIST_NEXT(&g->hop_list, hp, _global);
1115 MPLS_LIST_ADD_TAIL(&g->hop_list, h, _global, ldp_hop_list);
1118 void _ldp_global_del_hop_list(ldp_global * g, ldp_hop_list * h)
1120 MPLS_ASSERT(g && h);
1121 MPLS_LIST_REMOVE(&g->hop_list, h, _global);
1122 MPLS_REFCNT_RELEASE(h, ldp_hop_list_delete);
1125 void _ldp_global_add_fec(ldp_global * g, ldp_fec * f)
1127 ldp_fec *fp = NULL;
1129 MPLS_ASSERT(g && f);
1130 MPLS_REFCNT_HOLD(f);
1131 fp = MPLS_LIST_HEAD(&g->fec);
1132 while (fp != NULL) {
1133 if (fp->index > f->index) {
1134 MPLS_LIST_INSERT_BEFORE(&g->fec, fp, f, _global);
1135 return;
1137 fp = MPLS_LIST_NEXT(&g->fec, fp, _global);
1139 MPLS_LIST_ADD_TAIL(&g->fec, f, _global, ldp_fec);
1142 void _ldp_global_del_fec(ldp_global * g, ldp_fec * f)
1144 MPLS_ASSERT(g && f);
1145 MPLS_LIST_REMOVE(&g->fec, f, _global);
1146 MPLS_REFCNT_RELEASE(f, ldp_fec_delete);
1149 void _ldp_global_add_nexthop(ldp_global * g, ldp_nexthop * nh)
1151 ldp_nexthop *nhp = NULL;
1153 MPLS_ASSERT(g && nh);
1154 MPLS_REFCNT_HOLD(nh);
1155 nhp = MPLS_LIST_HEAD(&g->nexthop);
1156 while (nhp != NULL) {
1157 if (nhp->index > nh->index) {
1158 MPLS_LIST_INSERT_BEFORE(&g->nexthop, nhp, nh, _global);
1159 return;
1161 nhp = MPLS_LIST_NEXT(&g->nexthop, nhp, _global);
1163 MPLS_LIST_ADD_TAIL(&g->nexthop, nh, _global, ldp_nexthop);
1166 void _ldp_global_del_nexthop(ldp_global * g, ldp_nexthop * nh)
1168 MPLS_ASSERT(g && nh);
1169 MPLS_LIST_REMOVE(&g->nexthop, nh, _global);
1170 MPLS_REFCNT_RELEASE(nh, ldp_nexthop_delete);