Ability to walk global addr list
[mpls-ldp-portable.git] / ldp / ldp_global.c
blob2ca75605b386f4d4e044c0a83bdfd935af5d2505
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->addr, ldp_addr);
106 MPLS_LIST_INIT(&g->attr, ldp_attr);
107 MPLS_LIST_INIT(&g->peer, ldp_peer);
108 MPLS_LIST_INIT(&g->fec, ldp_fec);
109 MPLS_LIST_INIT(&g->adj, ldp_adj);
110 MPLS_LIST_INIT(&g->iff, ldp_if);
112 g->message_identifier = 1;
113 g->configuration_sequence_number = 1;
114 g->lsp_control_mode = LDP_GLOBAL_DEF_CONTROL_MODE;
115 g->label_retention_mode = LDP_GLOBAL_DEF_RETENTION_MODE;
116 g->lsp_repair_mode = LDP_GLOBAL_DEF_REPAIR_MODE;
117 g->propagate_release = LDP_GLOBAL_DEF_PROPOGATE_RELEASE;
118 g->label_merge = LDP_GLOBAL_DEF_LABEL_MERGE;
119 g->loop_detection_mode = LDP_GLOBAL_DEF_LOOP_DETECTION_MODE;
120 g->ttl_less_domain = LDP_GLOBAL_DEF_TTLLESS_DOMAIN;
121 g->local_tcp_port = LDP_GLOBAL_DEF_LOCAL_TCP_PORT;
122 g->local_udp_port = LDP_GLOBAL_DEF_LOCAL_UDP_PORT;
123 g->send_address_messages = LDP_GLOBAL_DEF_SEND_ADDR_MSG;
124 g->backoff_step = LDP_GLOBAL_DEF_BACKOFF_STEP;
125 g->send_lsrid_mapping = LDP_GLOBAL_DEF_SEND_LSRID_MAPPING;
126 g->no_route_to_peer_time = LDP_GLOBAL_DEF_NO_ROUTE_RETRY_TIME;
128 g->keepalive_timer = LDP_ENTITY_DEF_KEEPALIVE_TIMER;
129 g->keepalive_interval = LDP_ENTITY_DEF_KEEPALIVE_INTERVAL;
130 g->hellotime_timer = LDP_ENTITY_DEF_HELLOTIME_TIMER;
131 g->hellotime_interval = LDP_ENTITY_DEF_HELLOTIME_INTERVAL;
133 g->admin_state = MPLS_ADMIN_DISABLE;
134 g->user_data = data;
136 mpls_lock_release(g->global_lock);
138 LDP_EXIT(g->user_data, "ldp_global_create");
141 return g;
144 mpls_return_enum ldp_global_startup(ldp_global * g)
146 ldp_entity *e = NULL;
147 mpls_dest dest;
149 MPLS_ASSERT(g != NULL);
151 LDP_ENTER(g->user_data, "ldp_global_startup");
153 if (g->lsr_identifier.type == MPLS_FAMILY_NONE) {
154 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_ERROR,
155 "ldp_global_startup: invalid LSRID\n");
156 goto ldp_global_startup_cleanup;
159 g->timer_handle = mpls_timer_open(g->user_data);
160 if (mpls_timer_mgr_handle_verify(g->timer_handle) == MPLS_BOOL_FALSE) {
161 goto ldp_global_startup_cleanup;
164 g->socket_handle = mpls_socket_mgr_open(g->user_data);
165 if (mpls_socket_mgr_handle_verify(g->socket_handle) == MPLS_BOOL_FALSE) {
166 goto ldp_global_startup_cleanup;
169 g->ifmgr_handle = mpls_ifmgr_open(g->user_data, g);
170 if (mpls_ifmgr_handle_verify(g->ifmgr_handle) == MPLS_BOOL_FALSE) {
171 goto ldp_global_startup_cleanup;
174 g->fib_handle = mpls_fib_open(g->user_data, g);
175 if (mpls_fib_handle_verify(g->fib_handle) == MPLS_BOOL_FALSE) {
176 goto ldp_global_startup_cleanup;
179 #if MPLS_USE_LSR
180 if (!g->lsr_handle) {
181 goto ldp_global_startup_cleanup;
183 #else
184 g->mpls_handle = mpls_mpls_open(g->user_data);
185 if (mpls_mpls_handle_verify(g->mpls_handle) == MPLS_BOOL_FALSE) {
186 goto ldp_global_startup_cleanup;
188 #endif
190 g->addr_tree = mpls_tree_create(32);
191 g->fec_tree = mpls_tree_create(32);
193 g->hello_socket = mpls_socket_create_udp(g->socket_handle);
194 if (mpls_socket_handle_verify(g->socket_handle, g->hello_socket) == MPLS_BOOL_FALSE) {
195 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
196 "ldp_global_startup: error creating UDP socket\n");
197 goto ldp_global_startup_cleanup;
200 dest.addr.type = MPLS_FAMILY_IPV4;
201 dest.port = g->local_udp_port;
202 dest.addr.u.ipv4 = INADDR_ANY;
203 // dest.addr.u.ipv4 = INADDR_ALLRTRS_GROUP;
205 if (mpls_socket_bind(g->socket_handle, g->hello_socket, &dest) == MPLS_FAILURE) {
206 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
207 "ldp_global_startup: error binding UDP socket\n");
208 goto ldp_global_startup_cleanup;
211 if (mpls_socket_options(g->socket_handle, g->hello_socket,
212 MPLS_SOCKOP_NONBLOCK | MPLS_SOCKOP_REUSE) == MPLS_FAILURE) {
213 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
214 "ldp_global_startup: error setting UDP socket options\n");
215 goto ldp_global_startup_cleanup;
217 if (mpls_socket_multicast_options(g->socket_handle, g->hello_socket, 1, 0) ==
218 MPLS_FAILURE) {
219 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
220 "ldp_global_startup: error setting UDP socket multicast options\n");
221 goto ldp_global_startup_cleanup;
223 mpls_socket_readlist_add(g->socket_handle, g->hello_socket, 0, MPLS_SOCKET_UDP_DATA);
225 g->listen_socket = mpls_socket_create_tcp(g->socket_handle);
226 if (mpls_socket_handle_verify(g->socket_handle, g->listen_socket) == MPLS_BOOL_FALSE) {
227 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
228 "ldp_global_startup: error creating TCP socket\n");
229 goto ldp_global_startup_cleanup;
231 if (mpls_socket_options(g->socket_handle, g->listen_socket,
232 MPLS_SOCKOP_NONBLOCK | MPLS_SOCKOP_REUSE) == MPLS_FAILURE) {
233 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
234 "ldp_global_startup: error setting TCP socket options\n");
235 goto ldp_global_startup_cleanup;
238 dest.addr.type = MPLS_FAMILY_IPV4;
239 dest.port = g->local_tcp_port;
240 dest.addr.u.ipv4 = INADDR_ANY;
242 if (mpls_socket_bind(g->socket_handle, g->listen_socket, &dest) == MPLS_FAILURE) {
243 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
244 "ldp_global_startup: error binding TCP socket\n");
245 goto ldp_global_startup_cleanup;
248 if (mpls_socket_tcp_listen(g->socket_handle, g->listen_socket, 15) ==
249 MPLS_FAILURE) {
250 LDP_TRACE_LOG(g->user_data, MPLS_TRACE_STATE_ALL, LDP_TRACE_FLAG_DEBUG,
251 "ldp_global_startup: error setting listen buffer for TCP socket\n");
252 goto ldp_global_startup_cleanup;
255 mpls_socket_readlist_add(g->socket_handle, g->listen_socket, 0,
256 MPLS_SOCKET_TCP_LISTEN);
259 mpls_if_handle iff;
260 mpls_inet_addr addr;
261 mpls_return_enum retval;
263 retval = mpls_ifmgr_getfirst_address(g->ifmgr_handle, &iff, &addr);
264 if (retval == MPLS_FATAL) {
265 goto ldp_global_startup_cleanup;
267 if (retval == MPLS_SUCCESS) {
268 do {
269 ldp_addr *a;
270 ldp_if *i;
271 if (!(a = ldp_addr_create(g, &addr))) {
272 goto ldp_global_startup_cleanup;
274 a->if_handle = iff;
275 if ((i = ldp_global_find_if_handle(g, iff))) {
276 ldp_if_add_addr(i, a);
278 } while (mpls_ifmgr_getnext_address(g->ifmgr_handle, &iff, &addr) ==
279 MPLS_SUCCESS);
283 mpls_fec fec;
284 mpls_nexthop nexthop;
285 mpls_return_enum retval;
287 retval = mpls_fib_getfirst_route(g->fib_handle, &fec, &nexthop);
288 if (retval == MPLS_FATAL) {
289 goto ldp_global_startup_cleanup;
291 if (retval == MPLS_SUCCESS) {
292 do {
293 ldp_nexthop *n;
294 ldp_fec *f;
296 if (!(f = ldp_fec_find(g, &fec))) {
297 f = ldp_fec_insert(g, &fec);
298 if (f) {
299 _ldp_global_add_fec(g, f);
302 if (!f) {
303 goto ldp_global_startup_cleanup;
306 n = ldp_nexthop_create();
307 if (!n) {
308 goto ldp_global_startup_cleanup;
311 memcpy(&n->info, &nexthop, sizeof(mpls_nexthop));
312 n->type = nexthop.type;
313 if (ldp_fec_add_nexthop(g, f, n) != MPLS_SUCCESS) {
314 goto ldp_global_startup_cleanup;
316 } while (mpls_fib_getnext_route(g->fib_handle, &fec, &nexthop) ==
317 MPLS_SUCCESS);
321 e = MPLS_LIST_HEAD(&g->entity);
322 while (e != NULL) {
323 ldp_entity_startup(g, e);
324 e = MPLS_LIST_NEXT(&g->entity, e, _global);
327 g->admin_state = MPLS_ADMIN_ENABLE;
329 LDP_EXIT(g->user_data, "ldp_global_startup");
330 return MPLS_SUCCESS;
332 ldp_global_startup_cleanup:
333 ldp_global_shutdown(g);
334 mpls_socket_close(g->socket_handle, g->hello_socket);
335 mpls_socket_close(g->socket_handle, g->listen_socket);
336 g->hello_socket = 0;
337 g->listen_socket = 0;
339 LDP_EXIT(g->user_data, "ldp_global_startup-error");
341 return MPLS_FAILURE;
344 mpls_return_enum ldp_global_shutdown(ldp_global * g)
346 ldp_entity *e = NULL;
348 MPLS_ASSERT(g);
350 LDP_ENTER(g->user_data, "ldp_global_shutdown");
352 e = MPLS_LIST_HEAD(&g->entity);
353 while (e != NULL) {
354 ldp_entity_shutdown(g, e, 1);
355 e = MPLS_LIST_NEXT(&g->entity, e, _global);
358 g->admin_state = MPLS_ADMIN_DISABLE;
361 ldp_nexthop *n;
362 ldp_fec *f;
363 while ((f = MPLS_LIST_HEAD(&g->fec))) {
364 while ((n = MPLS_LIST_HEAD(&f->nh_root))) {
365 ldp_fec_del_nexthop(g, f, n);
367 _ldp_global_del_fec(g, f);
371 ldp_addr *a;
372 ldp_if *i;
373 while ((i = MPLS_LIST_HEAD(&g->iff))) {
374 while ((a = MPLS_LIST_HEAD(&i->addr_root))) {
375 ldp_if_del_addr(g, i, a);
377 ldp_if_remove(g, i);
381 mpls_socket_readlist_del(g->socket_handle, g->hello_socket);
382 mpls_socket_close(g->socket_handle, g->hello_socket);
384 mpls_socket_readlist_del(g->socket_handle, g->listen_socket);
385 mpls_socket_close(g->socket_handle, g->listen_socket);
387 mpls_tree_delete(g->addr_tree);
388 mpls_tree_delete(g->fec_tree);
390 mpls_lock_release(g->global_lock);
391 mpls_timer_close(g->timer_handle);
392 mpls_lock_get(g->global_lock);
394 mpls_socket_mgr_close(g->socket_handle);
395 mpls_ifmgr_close(g->ifmgr_handle);
396 mpls_fib_close(g->fib_handle);
398 #if MPLS_USE_LSR
399 #else
400 mpls_mpls_close(g->mpls_handle);
401 #endif
403 LDP_EXIT(g->user_data, "ldp_global_shutdown");
405 return MPLS_SUCCESS;
408 mpls_return_enum ldp_global_delete(ldp_global * g)
410 if (g) {
411 mpls_lock_delete(g->global_lock);
412 LDP_PRINT(g->user_data, "global delete\n");
413 mpls_free(g);
415 return MPLS_SUCCESS;
418 void _ldp_global_add_attr(ldp_global * g, ldp_attr * a)
420 ldp_attr *ap = NULL;
422 MPLS_ASSERT(g && a);
423 MPLS_REFCNT_HOLD(a);
424 ap = MPLS_LIST_HEAD(&g->attr);
425 while (ap != NULL) {
426 if (ap->index > a->index) {
427 MPLS_LIST_INSERT_BEFORE(&g->attr, ap, a, _global);
428 return;
430 ap = MPLS_LIST_NEXT(&g->attr, ap, _global);
432 MPLS_LIST_ADD_TAIL(&g->attr, a, _global, ldp_attr);
435 void _ldp_global_del_attr(ldp_global * g, ldp_attr * a)
437 MPLS_ASSERT(g && a);
438 MPLS_LIST_REMOVE(&g->attr, a, _global);
439 MPLS_REFCNT_RELEASE(a, ldp_attr_delete);
442 void _ldp_global_add_peer(ldp_global * g, ldp_peer * p)
444 ldp_peer *pp = NULL;
446 MPLS_ASSERT(g && p);
447 MPLS_REFCNT_HOLD(p);
448 pp = MPLS_LIST_HEAD(&g->peer);
449 while (pp != NULL) {
450 if (pp->index > p->index) {
451 MPLS_LIST_INSERT_BEFORE(&g->peer, pp, p, _global);
452 return;
454 pp = MPLS_LIST_NEXT(&g->peer, pp, _global);
456 MPLS_LIST_ADD_TAIL(&g->peer, p, _global, ldp_peer);
459 void _ldp_global_del_peer(ldp_global * g, ldp_peer * p)
461 MPLS_ASSERT(g && p);
462 MPLS_LIST_REMOVE(&g->peer, p, _global);
463 MPLS_REFCNT_RELEASE(p, ldp_peer_delete);
467 * _ldp_global_add_if/del_if and _ldp_global_add_addr/del_addr are
468 * not the same as the rest of the global_add/del functions. They
469 * do not hold refcnts, they are used as part of the create and delete
470 * process of these structures
473 void _ldp_global_add_if(ldp_global * g, ldp_if * i)
475 ldp_if *ip = NULL;
477 MPLS_ASSERT(g && i);
478 ip = MPLS_LIST_HEAD(&g->iff);
479 while (ip != NULL) {
480 if (ip->index > i->index) {
481 MPLS_LIST_INSERT_BEFORE(&g->iff, ip, i, _global);
482 return;
484 ip = MPLS_LIST_NEXT(&g->iff, ip, _global);
486 MPLS_LIST_ADD_TAIL(&g->iff, i, _global, ldp_if);
489 void _ldp_global_del_if(ldp_global * g, ldp_if * i)
491 MPLS_ASSERT(g && i);
492 MPLS_LIST_REMOVE(&g->iff, i, _global);
495 void _ldp_global_add_addr(ldp_global * g, ldp_addr * a)
497 ldp_addr *ap = NULL;
499 MPLS_ASSERT(g && a);
500 ap = MPLS_LIST_HEAD(&g->addr);
501 while (ap != NULL) {
502 if (ap->index > a->index) {
503 MPLS_LIST_INSERT_BEFORE(&g->addr, ap, a, _global);
504 return;
506 ap = MPLS_LIST_NEXT(&g->addr, ap, _global);
508 MPLS_LIST_ADD_TAIL(&g->addr, a, _global, ldp_addr);
511 void _ldp_global_del_addr(ldp_global * g, ldp_addr * a)
513 MPLS_ASSERT(g && a);
514 MPLS_LIST_REMOVE(&g->addr, a, _global);
519 void _ldp_global_add_adj(ldp_global * g, ldp_adj * a)
521 ldp_adj *ap = NULL;
523 MPLS_ASSERT(g && a);
524 MPLS_REFCNT_HOLD(a);
525 ap = MPLS_LIST_HEAD(&g->adj);
526 while (ap != NULL) {
527 if (ap->index > a->index) {
528 MPLS_LIST_INSERT_BEFORE(&g->adj, ap, a, _global);
529 return;
531 ap = MPLS_LIST_NEXT(&g->adj, ap, _global);
533 MPLS_LIST_ADD_TAIL(&g->adj, a, _global, ldp_adj);
536 void _ldp_global_del_adj(ldp_global * g, ldp_adj * a)
538 MPLS_ASSERT(g && a);
539 MPLS_LIST_REMOVE(&g->adj, a, _global);
540 MPLS_REFCNT_RELEASE(a, ldp_adj_delete);
543 void _ldp_global_add_entity(ldp_global * g, ldp_entity * e)
545 ldp_entity *ep = NULL;
547 MPLS_ASSERT(g && e);
548 MPLS_REFCNT_HOLD(e);
549 ep = MPLS_LIST_HEAD(&g->entity);
550 while (ep != NULL) {
551 if (ep->index > e->index) {
552 MPLS_LIST_INSERT_BEFORE(&g->entity, ep, e, _global);
553 return;
555 ep = MPLS_LIST_NEXT(&g->entity, ep, _global);
557 MPLS_LIST_ADD_TAIL(&g->entity, e, _global, ldp_entity);
560 void _ldp_global_del_entity(ldp_global * g, ldp_entity * e)
562 MPLS_ASSERT(g && e);
563 MPLS_LIST_REMOVE(&g->entity, e, _global);
564 MPLS_REFCNT_RELEASE(e, ldp_entity_delete);
567 void _ldp_global_add_session(ldp_global * g, ldp_session * s)
569 ldp_session *sp = NULL;
571 MPLS_ASSERT(g && s);
572 MPLS_REFCNT_HOLD(s);
573 s->on_global = MPLS_BOOL_TRUE;
574 sp = MPLS_LIST_HEAD(&g->session);
575 while (sp != NULL) {
576 if (sp->index > s->index) {
577 MPLS_LIST_INSERT_BEFORE(&g->session, sp, s, _global);
578 return;
580 sp = MPLS_LIST_NEXT(&g->session, sp, _global);
582 MPLS_LIST_ADD_TAIL(&g->session, s, _global, ldp_session);
585 void _ldp_global_del_session(ldp_global * g, ldp_session * s)
587 MPLS_ASSERT(g && s);
588 MPLS_ASSERT(s->on_global == MPLS_BOOL_TRUE);
589 MPLS_LIST_REMOVE(&g->session, s, _global);
590 s->on_global = MPLS_BOOL_FALSE;
591 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
594 mpls_return_enum _ldp_global_add_inlabel(ldp_global * g, ldp_inlabel * i)
596 ldp_inlabel *ip = NULL;
597 mpls_return_enum result;
599 MPLS_ASSERT(g && i);
601 #if MPLS_USE_LSR
603 lsr_insegment iseg;
604 memcpy(&iseg.info,&i->info,sizeof(mpls_insegment));
605 result = lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_ADD|
606 LSR_INSEGMENT_CFG_NPOP|LSR_INSEGMENT_CFG_FAMILY|
607 LSR_INSEGMENT_CFG_LABELSPACE|LSR_INSEGMENT_CFG_LABEL|
608 LSR_INSEGMENT_CFG_OWNER);
609 memcpy(&i->info, &iseg.info, sizeof(mpls_insegment));
610 i->info.handle = iseg.index;
612 #else
613 result = mpls_mpls_insegment_add(g->mpls_handle, &i->info);
614 #endif
615 if (result != MPLS_SUCCESS) {
616 return result;
619 MPLS_REFCNT_HOLD(i);
620 ip = MPLS_LIST_HEAD(&g->inlabel);
621 while (ip != NULL) {
622 if (ip->index > i->index) {
623 MPLS_LIST_INSERT_BEFORE(&g->inlabel, ip, i, _global);
624 return MPLS_SUCCESS;
626 ip = MPLS_LIST_NEXT(&g->inlabel, ip, _global);
628 MPLS_LIST_ADD_TAIL(&g->inlabel, i, _global, ldp_inlabel);
629 return MPLS_SUCCESS;
632 mpls_return_enum _ldp_global_del_inlabel(ldp_global * g, ldp_inlabel * i)
634 MPLS_ASSERT(g && i);
635 MPLS_ASSERT(i->reuse_count == 0);
636 #if MPLS_USE_LSR
638 lsr_insegment iseg;
639 iseg.index = i->info.handle;
640 lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_DEL);
642 #else
643 mpls_mpls_insegment_del(g->mpls_handle, &i->info);
644 #endif
645 MPLS_LIST_REMOVE(&g->inlabel, i, _global);
646 MPLS_REFCNT_RELEASE(i, ldp_inlabel_delete);
647 return MPLS_SUCCESS;
650 mpls_return_enum _ldp_global_add_outlabel(ldp_global * g, ldp_outlabel * o)
652 ldp_outlabel *op = NULL;
653 mpls_return_enum result;
655 MPLS_ASSERT(g && o);
656 #if MPLS_USE_LSR
658 lsr_outsegment oseg;
659 memcpy(&oseg.info, &o->info, sizeof(mpls_outsegment));
660 result = lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_ADD|
661 LSR_OUTSEGMENT_CFG_PUSH_LABEL|LSR_OUTSEGMENT_CFG_OWNER|
662 LSR_OUTSEGMENT_CFG_INTERFACE|LSR_OUTSEGMENT_CFG_LABEL|
663 LSR_OUTSEGMENT_CFG_NEXTHOP);
664 o->info.handle = oseg.index;
666 #else
667 result = mpls_mpls_outsegment_add(g->mpls_handle, &o->info);
668 #endif
670 if (result != MPLS_SUCCESS) {
671 return result;
674 MPLS_REFCNT_HOLD(o);
675 o->switching = MPLS_BOOL_TRUE;
676 op = MPLS_LIST_HEAD(&g->outlabel);
677 while (op != NULL) {
678 if (op->index > o->index) {
679 MPLS_LIST_INSERT_BEFORE(&g->outlabel, op, o, _global);
680 return MPLS_SUCCESS;
682 op = MPLS_LIST_NEXT(&g->outlabel, op, _global);
684 MPLS_LIST_ADD_TAIL(&g->outlabel, o, _global, ldp_outlabel);
685 return MPLS_SUCCESS;
688 mpls_return_enum _ldp_global_del_outlabel(ldp_global * g, ldp_outlabel * o)
690 MPLS_ASSERT(g && o);
691 #if MPLS_USE_LSR
693 lsr_outsegment oseg;
694 oseg.index = o->info.handle;
695 lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_DEL);
697 #else
698 mpls_mpls_outsegment_del(g->mpls_handle, &o->info);
699 #endif
701 o->switching = MPLS_BOOL_FALSE;
702 MPLS_ASSERT(o->merge_count == 0);
703 MPLS_LIST_REMOVE(&g->outlabel, o, _global);
704 MPLS_REFCNT_RELEASE(o, ldp_outlabel_delete);
705 return MPLS_SUCCESS;
708 mpls_return_enum ldp_global_find_attr_index(ldp_global * g, uint32_t index,
709 ldp_attr ** attr)
711 ldp_attr *a = NULL;
713 if (g && index > 0) {
715 /* because we sort our inserts by index, this lets us know
716 if we've "walked" past the end of the list */
718 a = MPLS_LIST_TAIL(&g->attr);
719 if (a == NULL || a->index < index) {
720 return MPLS_END_OF_LIST;
721 *attr = NULL;
724 a = MPLS_LIST_HEAD(&g->attr);
725 while (a != NULL) {
726 if (a->index == index) {
727 *attr = a;
728 return MPLS_SUCCESS;
730 a = MPLS_LIST_NEXT(&g->attr, a, _global);
733 *attr = NULL;
734 return MPLS_FAILURE;
737 mpls_return_enum ldp_global_find_session_index(ldp_global * g, uint32_t index,
738 ldp_session ** session)
740 ldp_session *s = NULL;
742 if (g && index > 0) {
744 /* because we sort our inserts by index, this lets us know
745 if we've "walked" past the end of the list */
747 s = MPLS_LIST_TAIL(&g->session);
748 if (s == NULL || s->index < index) {
749 *session = NULL;
750 return MPLS_END_OF_LIST;
753 s = MPLS_LIST_HEAD(&g->session);
754 while (s != NULL) {
755 if (s->index == index) {
756 *session = s;
757 return MPLS_SUCCESS;
759 s = MPLS_LIST_NEXT(&g->session, s, _global);
762 *session = NULL;
763 return MPLS_FAILURE;
766 mpls_return_enum ldp_global_find_inlabel_index(ldp_global * g, uint32_t index,
767 ldp_inlabel ** inlabel)
769 ldp_inlabel *i = NULL;
771 if (g && index > 0) {
773 /* because we sort our inserts by index, this lets us know
774 if we've "walked" past the end of the list */
776 i = MPLS_LIST_TAIL(&g->inlabel);
777 if (i == NULL || i->index < index) {
778 *inlabel = NULL;
779 return MPLS_END_OF_LIST;
782 i = MPLS_LIST_HEAD(&g->inlabel);
783 while (i != NULL) {
784 if (i->index == index) {
785 *inlabel = i;
786 return MPLS_SUCCESS;
788 i = MPLS_LIST_NEXT(&g->inlabel, i, _global);
791 *inlabel = NULL;
792 return MPLS_FAILURE;
795 mpls_return_enum ldp_global_find_outlabel_index(ldp_global * g, uint32_t index,
796 ldp_outlabel ** outlabel)
798 ldp_outlabel *o = NULL;
800 if (g && index > 0) {
802 /* because we sort our inserts by index, this lets us know
803 if we've "walked" past the end of the list */
805 o = MPLS_LIST_TAIL(&g->outlabel);
806 if (o == NULL || o->index < index) {
807 *outlabel = NULL;
808 return MPLS_END_OF_LIST;
811 o = MPLS_LIST_HEAD(&g->outlabel);
812 while (o != NULL) {
813 if (o->index == index) {
814 *outlabel = o;
815 return MPLS_SUCCESS;
817 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
820 *outlabel = NULL;
821 return MPLS_FAILURE;
824 ldp_outlabel *ldp_global_find_outlabel_handle(ldp_global * g,
825 mpls_outsegment_handle handle)
827 ldp_outlabel *o = MPLS_LIST_HEAD(&g->outlabel);
829 if (g) {
830 while (o != NULL) {
831 if (!mpls_outsegment_handle_compare(o->info.handle, handle))
832 return o;
834 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
837 return NULL;
840 mpls_return_enum ldp_global_find_entity_index(ldp_global * g, uint32_t index,
841 ldp_entity ** entity)
843 ldp_entity *e = NULL;
845 if (g && index > 0) {
847 /* because we sort our inserts by index, this lets us know
848 if we've "walked" past the end of the list */
850 e = MPLS_LIST_TAIL(&g->entity);
851 if (e == NULL || e->index < index) {
852 *entity = NULL;
853 return MPLS_END_OF_LIST;
856 e = MPLS_LIST_HEAD(&g->entity);
857 while (e != NULL) {
858 if (e->index == index) {
859 *entity = e;
860 return MPLS_SUCCESS;
862 e = MPLS_LIST_NEXT(&g->entity, e, _global);
865 *entity = NULL;
866 return MPLS_FAILURE;
869 ldp_peer *ldp_global_find_peer_addr(ldp_global * g, mpls_inet_addr * addr)
871 ldp_peer *p;
873 MPLS_ASSERT(g && addr);
875 /* JLEU: we will need to add a tree to optimize this search,
876 known peers will be in tree, unknown will take a "slow path" to
877 verify them, then be added to tree */
879 p = MPLS_LIST_HEAD(&g->peer);
880 while (p) {
881 LDP_PRINT(g->user_data,
882 "ldp_global_find_peer_lsrid: peer: %08x lsrid: %08x\n",
883 p->dest.addr.u.ipv4, addr->u.ipv4);
884 if (!mpls_inet_addr_compare(&p->dest.addr, addr)) {
885 return p;
887 p = MPLS_LIST_NEXT(&g->peer, p, _global);
889 return NULL;
892 mpls_return_enum ldp_global_find_adj_index(ldp_global * g, uint32_t index,
893 ldp_adj ** adj)
895 ldp_adj *a = 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 a = MPLS_LIST_TAIL(&g->adj);
902 if (a == NULL || a->index < index) {
903 return MPLS_END_OF_LIST;
904 *adj = NULL;
907 a = MPLS_LIST_HEAD(&g->adj);
908 while (a != NULL) {
909 if (a->index == index) {
910 *adj = a;
911 return MPLS_SUCCESS;
913 a = MPLS_LIST_NEXT(&g->adj, a, _global);
916 *adj = NULL;
917 return MPLS_FAILURE;
920 mpls_return_enum ldp_global_find_peer_index(ldp_global * g, uint32_t index,
921 ldp_peer ** peer)
923 ldp_peer *p = 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 p = MPLS_LIST_TAIL(&g->peer);
930 if (p == NULL || p->index < index) {
931 *peer = NULL;
932 return MPLS_END_OF_LIST;
935 p = MPLS_LIST_HEAD(&g->peer);
936 while (p != NULL) {
937 if (p->index == index) {
938 *peer = p;
939 return MPLS_SUCCESS;
941 p = MPLS_LIST_NEXT(&g->peer, p, _global);
944 *peer = NULL;
945 return MPLS_FAILURE;
948 mpls_return_enum ldp_global_find_fec_index(ldp_global * g, uint32_t index,
949 ldp_fec ** fec)
951 ldp_fec *f = NULL;
953 if (g && index > 0) {
954 /* because we sort our inserts by index, this lets us know
955 if we've "walked" past the end of the list */
957 f = MPLS_LIST_TAIL(&g->fec);
958 if (f == NULL || f->index < index) {
959 *fec = NULL;
960 return MPLS_END_OF_LIST;
963 f = MPLS_LIST_HEAD(&g->fec);
964 while (f != NULL) {
965 if (f->index == index) {
966 *fec = f;
967 return MPLS_SUCCESS;
969 f = MPLS_LIST_NEXT(&g->fec, f, _global);
972 *fec = NULL;
973 return MPLS_FAILURE;
976 mpls_return_enum ldp_global_find_fec(ldp_global * g, mpls_fec * m,
977 ldp_fec ** fec)
979 ldp_fec *f = NULL;
981 MPLS_ASSERT(g && m);
983 f = MPLS_LIST_HEAD(&g->fec);
984 do {
985 if (!mpls_fec_compare(m, &f->info)) {
986 *fec = f;
987 return MPLS_SUCCESS;
989 } while((f = MPLS_LIST_NEXT(&g->fec, f, _global)));
990 *fec = NULL;
991 return MPLS_FAILURE;
994 mpls_return_enum ldp_global_find_addr_index(ldp_global * g, uint32_t index,
995 ldp_addr ** addr)
997 ldp_addr *a = NULL;
999 if (g && index > 0) {
1001 /* because we sort our inserts by index, this lets us know
1002 if we've "walked" past the end of the list */
1004 a = MPLS_LIST_TAIL(&g->addr);
1005 if (a == NULL || a->index < index) {
1006 *addr = NULL;
1007 return MPLS_END_OF_LIST;
1010 a = MPLS_LIST_HEAD(&g->addr);
1011 while (a != NULL) {
1012 if (a->index == index) {
1013 *addr = a;
1014 return MPLS_SUCCESS;
1016 a = MPLS_LIST_NEXT(&g->addr, a, _global);
1019 *addr = NULL;
1020 return MPLS_FAILURE;
1023 mpls_return_enum ldp_global_find_if_index(ldp_global * g, uint32_t index,
1024 ldp_if ** iff)
1026 ldp_if *i = NULL;
1028 if (g && index > 0) {
1030 /* because we sort our inserts by index, this lets us know
1031 if we've "walked" past the end of the list */
1033 i = MPLS_LIST_TAIL(&g->iff);
1034 if (i == NULL || i->index < index) {
1035 *iff = NULL;
1036 return MPLS_END_OF_LIST;
1039 i = MPLS_LIST_HEAD(&g->iff);
1040 while (i != NULL) {
1041 if (i->index == index) {
1042 *iff = i;
1043 return MPLS_SUCCESS;
1045 i = MPLS_LIST_NEXT(&g->iff, i, _global);
1048 *iff = NULL;
1049 return MPLS_FAILURE;
1052 ldp_if *ldp_global_find_if_handle(ldp_global * g, mpls_if_handle handle)
1054 ldp_if *i = MPLS_LIST_HEAD(&g->iff);
1056 if (g) {
1057 while (i != NULL) {
1058 if (!mpls_if_handle_compare(i->handle, handle))
1059 return i;
1061 i = MPLS_LIST_NEXT(&g->iff, i, _global);
1064 return NULL;
1067 ldp_adj *ldp_global_find_adj_ldpid(ldp_global * g, mpls_inet_addr * lsraddr,
1068 int labelspace)
1071 ldp_adj *a = MPLS_LIST_HEAD(&g->adj);
1073 while (a != NULL) {
1074 if ((!mpls_inet_addr_compare(lsraddr, &a->remote_lsr_address)) &&
1075 labelspace == a->remote_label_space)
1076 return a;
1078 a = MPLS_LIST_NEXT(&g->adj, a, _global);
1080 return NULL;
1083 mpls_return_enum ldp_global_find_tunnel_index(ldp_global * g, uint32_t index,
1084 ldp_tunnel ** tunnel)
1086 ldp_tunnel *t = 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 t = MPLS_LIST_TAIL(&g->tunnel);
1093 if (t == NULL || t->index < index) {
1094 *tunnel = NULL;
1095 return MPLS_END_OF_LIST;
1098 t = MPLS_LIST_HEAD(&g->tunnel);
1099 while (t != NULL) {
1100 if (t->index == index) {
1101 *tunnel = t;
1102 return MPLS_SUCCESS;
1104 t = MPLS_LIST_NEXT(&g->tunnel, t, _global);
1107 *tunnel = NULL;
1108 return MPLS_FAILURE;
1111 mpls_return_enum ldp_global_find_resource_index(ldp_global * g, uint32_t index,
1112 ldp_resource ** resource)
1114 ldp_resource *r = 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 r = MPLS_LIST_TAIL(&g->resource);
1121 if (r == NULL || r->index < index) {
1122 *resource = NULL;
1123 return MPLS_END_OF_LIST;
1126 r = MPLS_LIST_HEAD(&g->resource);
1127 while (r != NULL) {
1128 if (r->index == index) {
1129 *resource = r;
1130 return MPLS_SUCCESS;
1132 r = MPLS_LIST_NEXT(&g->resource, r, _global);
1135 *resource = NULL;
1136 return MPLS_FAILURE;
1139 mpls_return_enum ldp_global_find_hop_list_index(ldp_global * g, uint32_t index,
1140 ldp_hop_list ** hop_list)
1142 ldp_hop_list *h = NULL;
1144 if (g && index > 0) {
1145 /* because we sort our inserts by index, this lets us know
1146 if we've "walked" past the end of the list */
1148 h = MPLS_LIST_TAIL(&g->hop_list);
1149 if (h == NULL || h->index < index) {
1150 *hop_list = NULL;
1151 return MPLS_END_OF_LIST;
1154 h = MPLS_LIST_HEAD(&g->hop_list);
1155 while (h != NULL) {
1156 if (h->index == index) {
1157 *hop_list = h;
1158 return MPLS_SUCCESS;
1160 h = MPLS_LIST_NEXT(&g->hop_list, h, _global);
1163 *hop_list = NULL;
1164 return MPLS_FAILURE;
1167 void _ldp_global_add_tunnel(ldp_global * g, ldp_tunnel * t)
1169 ldp_tunnel *tp = NULL;
1171 MPLS_ASSERT(g && t);
1172 MPLS_REFCNT_HOLD(t);
1173 tp = MPLS_LIST_HEAD(&g->tunnel);
1174 while (tp != NULL) {
1175 if (tp->index > t->index) {
1176 MPLS_LIST_INSERT_BEFORE(&g->tunnel, tp, t, _global);
1177 return;
1179 tp = MPLS_LIST_NEXT(&g->tunnel, tp, _global);
1181 MPLS_LIST_ADD_TAIL(&g->tunnel, t, _global, ldp_tunnel);
1184 void _ldp_global_del_tunnel(ldp_global * g, ldp_tunnel * t)
1186 MPLS_ASSERT(g && t);
1187 MPLS_LIST_REMOVE(&g->tunnel, t, _global);
1188 MPLS_REFCNT_RELEASE(t, ldp_tunnel_delete);
1191 void _ldp_global_add_resource(ldp_global * g, ldp_resource * r)
1193 ldp_resource *rp = NULL;
1195 MPLS_ASSERT(g && r);
1196 MPLS_REFCNT_HOLD(r);
1197 rp = MPLS_LIST_HEAD(&g->resource);
1198 while (rp != NULL) {
1199 if (rp->index > r->index) {
1200 MPLS_LIST_INSERT_BEFORE(&g->resource, rp, r, _global);
1201 return;
1203 rp = MPLS_LIST_NEXT(&g->resource, rp, _global);
1205 MPLS_LIST_ADD_TAIL(&g->resource, r, _global, ldp_resource);
1208 void _ldp_global_del_resource(ldp_global * g, ldp_resource * r)
1210 MPLS_ASSERT(g && r);
1211 MPLS_LIST_REMOVE(&g->resource, r, _global);
1212 MPLS_REFCNT_RELEASE(r, ldp_resource_delete);
1215 void _ldp_global_add_hop_list(ldp_global * g, ldp_hop_list * h)
1217 ldp_hop_list *hp = NULL;
1219 MPLS_ASSERT(g && h);
1220 MPLS_REFCNT_HOLD(h);
1221 hp = MPLS_LIST_HEAD(&g->hop_list);
1222 while (hp != NULL) {
1223 if (hp->index > h->index) {
1224 MPLS_LIST_INSERT_BEFORE(&g->hop_list, hp, h, _global);
1225 return;
1227 hp = MPLS_LIST_NEXT(&g->hop_list, hp, _global);
1229 MPLS_LIST_ADD_TAIL(&g->hop_list, h, _global, ldp_hop_list);
1232 void _ldp_global_del_hop_list(ldp_global * g, ldp_hop_list * h)
1234 MPLS_ASSERT(g && h);
1235 MPLS_LIST_REMOVE(&g->hop_list, h, _global);
1236 MPLS_REFCNT_RELEASE(h, ldp_hop_list_delete);
1239 void _ldp_global_add_fec(ldp_global * g, ldp_fec * f)
1241 ldp_fec *fp = NULL;
1243 MPLS_ASSERT(g && f);
1244 MPLS_REFCNT_HOLD(f);
1245 fp = MPLS_LIST_HEAD(&g->fec);
1246 while (fp != NULL) {
1247 if (fp->index > f->index) {
1248 MPLS_LIST_INSERT_BEFORE(&g->fec, fp, f, _global);
1249 return;
1251 fp = MPLS_LIST_NEXT(&g->fec, fp, _global);
1253 MPLS_LIST_ADD_TAIL(&g->fec, f, _global, ldp_fec);
1256 void _ldp_global_del_fec(ldp_global * g, ldp_fec * f)
1258 MPLS_ASSERT(g && f);
1259 MPLS_LIST_REMOVE(&g->fec, f, _global);
1260 MPLS_REFCNT_RELEASE(f, ldp_fec_delete);
1263 void _ldp_global_add_nexthop(ldp_global * g, ldp_nexthop * nh)
1265 ldp_nexthop *nhp = NULL;
1267 MPLS_ASSERT(g && nh);
1268 MPLS_REFCNT_HOLD(nh);
1269 nhp = MPLS_LIST_HEAD(&g->nexthop);
1270 while (nhp != NULL) {
1271 if (nhp->index > nh->index) {
1272 MPLS_LIST_INSERT_BEFORE(&g->nexthop, nhp, nh, _global);
1273 return;
1275 nhp = MPLS_LIST_NEXT(&g->nexthop, nhp, _global);
1277 MPLS_LIST_ADD_TAIL(&g->nexthop, nh, _global, ldp_nexthop);
1280 void _ldp_global_del_nexthop(ldp_global * g, ldp_nexthop * nh)
1282 MPLS_ASSERT(g && nh);
1283 MPLS_LIST_REMOVE(&g->nexthop, nh, _global);
1284 MPLS_REFCNT_RELEASE(nh, ldp_nexthop_delete);