Added debugging to help figure out why FEC were disappearing.
[mpls-ldp-portable.git] / ldp / ldp_global.c
blob197883120396a495cede8a3021c20afd5b16ba40
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 _ldp_global_add_nexthop(g, n);
317 } while (mpls_fib_getnext_route(g->fib_handle, &fec, &nexthop) ==
318 MPLS_SUCCESS);
322 e = MPLS_LIST_HEAD(&g->entity);
323 while (e != NULL) {
324 ldp_entity_startup(g, e);
325 e = MPLS_LIST_NEXT(&g->entity, e, _global);
328 g->admin_state = MPLS_ADMIN_ENABLE;
330 LDP_EXIT(g->user_data, "ldp_global_startup");
331 return MPLS_SUCCESS;
333 ldp_global_startup_cleanup:
334 ldp_global_shutdown(g);
335 mpls_socket_close(g->socket_handle, g->hello_socket);
336 mpls_socket_close(g->socket_handle, g->listen_socket);
337 g->hello_socket = 0;
338 g->listen_socket = 0;
340 LDP_EXIT(g->user_data, "ldp_global_startup-error");
342 return MPLS_FAILURE;
345 mpls_return_enum ldp_global_shutdown(ldp_global * g)
347 ldp_entity *e = NULL;
349 MPLS_ASSERT(g);
351 LDP_ENTER(g->user_data, "ldp_global_shutdown");
353 e = MPLS_LIST_HEAD(&g->entity);
354 while (e != NULL) {
355 ldp_entity_shutdown(g, e, 1);
356 e = MPLS_LIST_NEXT(&g->entity, e, _global);
359 g->admin_state = MPLS_ADMIN_DISABLE;
362 ldp_nexthop *n;
363 ldp_fec *f;
364 while ((f = MPLS_LIST_HEAD(&g->fec))) {
365 while ((n = MPLS_LIST_HEAD(&f->nh_root))) {
366 ldp_fec_del_nexthop(g, f, n);
368 _ldp_global_del_fec(g, f);
372 ldp_addr *a;
373 ldp_if *i;
374 while ((i = MPLS_LIST_HEAD(&g->iff))) {
375 while ((a = MPLS_LIST_HEAD(&i->addr_root))) {
376 ldp_if_del_addr(g, i, a);
378 ldp_if_remove(g, i);
382 mpls_socket_readlist_del(g->socket_handle, g->hello_socket);
383 mpls_socket_close(g->socket_handle, g->hello_socket);
385 mpls_socket_readlist_del(g->socket_handle, g->listen_socket);
386 mpls_socket_close(g->socket_handle, g->listen_socket);
388 mpls_tree_delete(g->addr_tree);
389 mpls_tree_delete(g->fec_tree);
391 mpls_lock_release(g->global_lock);
392 mpls_timer_close(g->timer_handle);
393 mpls_lock_get(g->global_lock);
395 mpls_socket_mgr_close(g->socket_handle);
396 mpls_ifmgr_close(g->ifmgr_handle);
397 mpls_fib_close(g->fib_handle);
399 #if MPLS_USE_LSR
400 #else
401 mpls_mpls_close(g->mpls_handle);
402 #endif
404 LDP_EXIT(g->user_data, "ldp_global_shutdown");
406 return MPLS_SUCCESS;
409 mpls_return_enum ldp_global_delete(ldp_global * g)
411 if (g) {
412 mpls_lock_delete(g->global_lock);
413 LDP_PRINT(g->user_data, "global delete\n");
414 mpls_free(g);
416 return MPLS_SUCCESS;
419 void _ldp_global_add_attr(ldp_global * g, ldp_attr * a)
421 ldp_attr *ap = NULL;
423 MPLS_ASSERT(g && a);
424 MPLS_REFCNT_HOLD(a);
425 ap = MPLS_LIST_HEAD(&g->attr);
426 while (ap != NULL) {
427 if (ap->index > a->index) {
428 MPLS_LIST_INSERT_BEFORE(&g->attr, ap, a, _global);
429 return;
431 ap = MPLS_LIST_NEXT(&g->attr, ap, _global);
433 MPLS_LIST_ADD_TAIL(&g->attr, a, _global, ldp_attr);
436 void _ldp_global_del_attr(ldp_global * g, ldp_attr * a)
438 MPLS_ASSERT(g && a);
439 MPLS_LIST_REMOVE(&g->attr, a, _global);
440 MPLS_REFCNT_RELEASE(a, ldp_attr_delete);
443 void _ldp_global_add_peer(ldp_global * g, ldp_peer * p)
445 ldp_peer *pp = NULL;
447 MPLS_ASSERT(g && p);
448 MPLS_REFCNT_HOLD(p);
449 pp = MPLS_LIST_HEAD(&g->peer);
450 while (pp != NULL) {
451 if (pp->index > p->index) {
452 MPLS_LIST_INSERT_BEFORE(&g->peer, pp, p, _global);
453 return;
455 pp = MPLS_LIST_NEXT(&g->peer, pp, _global);
457 MPLS_LIST_ADD_TAIL(&g->peer, p, _global, ldp_peer);
460 void _ldp_global_del_peer(ldp_global * g, ldp_peer * p)
462 MPLS_ASSERT(g && p);
463 MPLS_LIST_REMOVE(&g->peer, p, _global);
464 MPLS_REFCNT_RELEASE(p, ldp_peer_delete);
468 * _ldp_global_add_if/del_if and _ldp_global_add_addr/del_addr are
469 * not the same as the rest of the global_add/del functions. They
470 * do not hold refcnts, they are used as part of the create and delete
471 * process of these structures
474 void _ldp_global_add_if(ldp_global * g, ldp_if * i)
476 ldp_if *ip = NULL;
478 MPLS_ASSERT(g && i);
479 ip = MPLS_LIST_HEAD(&g->iff);
480 while (ip != NULL) {
481 if (ip->index > i->index) {
482 MPLS_LIST_INSERT_BEFORE(&g->iff, ip, i, _global);
483 return;
485 ip = MPLS_LIST_NEXT(&g->iff, ip, _global);
487 MPLS_LIST_ADD_TAIL(&g->iff, i, _global, ldp_if);
490 void _ldp_global_del_if(ldp_global * g, ldp_if * i)
492 MPLS_ASSERT(g && i);
493 MPLS_LIST_REMOVE(&g->iff, i, _global);
496 void _ldp_global_add_addr(ldp_global * g, ldp_addr * a)
498 ldp_addr *ap = NULL;
500 MPLS_ASSERT(g && a);
501 ap = MPLS_LIST_HEAD(&g->addr);
502 while (ap != NULL) {
503 if (ap->index > a->index) {
504 MPLS_LIST_INSERT_BEFORE(&g->addr, ap, a, _global);
505 return;
507 ap = MPLS_LIST_NEXT(&g->addr, ap, _global);
509 MPLS_LIST_ADD_TAIL(&g->addr, a, _global, ldp_addr);
512 void _ldp_global_del_addr(ldp_global * g, ldp_addr * a)
514 MPLS_ASSERT(g && a);
515 MPLS_LIST_REMOVE(&g->addr, a, _global);
520 void _ldp_global_add_adj(ldp_global * g, ldp_adj * a)
522 ldp_adj *ap = NULL;
524 MPLS_ASSERT(g && a);
525 MPLS_REFCNT_HOLD(a);
526 ap = MPLS_LIST_HEAD(&g->adj);
527 while (ap != NULL) {
528 if (ap->index > a->index) {
529 MPLS_LIST_INSERT_BEFORE(&g->adj, ap, a, _global);
530 return;
532 ap = MPLS_LIST_NEXT(&g->adj, ap, _global);
534 MPLS_LIST_ADD_TAIL(&g->adj, a, _global, ldp_adj);
537 void _ldp_global_del_adj(ldp_global * g, ldp_adj * a)
539 MPLS_ASSERT(g && a);
540 MPLS_LIST_REMOVE(&g->adj, a, _global);
541 MPLS_REFCNT_RELEASE(a, ldp_adj_delete);
544 void _ldp_global_add_entity(ldp_global * g, ldp_entity * e)
546 ldp_entity *ep = NULL;
548 MPLS_ASSERT(g && e);
549 MPLS_REFCNT_HOLD(e);
550 ep = MPLS_LIST_HEAD(&g->entity);
551 while (ep != NULL) {
552 if (ep->index > e->index) {
553 MPLS_LIST_INSERT_BEFORE(&g->entity, ep, e, _global);
554 return;
556 ep = MPLS_LIST_NEXT(&g->entity, ep, _global);
558 MPLS_LIST_ADD_TAIL(&g->entity, e, _global, ldp_entity);
561 void _ldp_global_del_entity(ldp_global * g, ldp_entity * e)
563 MPLS_ASSERT(g && e);
564 MPLS_LIST_REMOVE(&g->entity, e, _global);
565 MPLS_REFCNT_RELEASE(e, ldp_entity_delete);
568 void _ldp_global_add_session(ldp_global * g, ldp_session * s)
570 ldp_session *sp = NULL;
572 MPLS_ASSERT(g && s);
573 MPLS_REFCNT_HOLD(s);
574 s->on_global = MPLS_BOOL_TRUE;
575 sp = MPLS_LIST_HEAD(&g->session);
576 while (sp != NULL) {
577 if (sp->index > s->index) {
578 MPLS_LIST_INSERT_BEFORE(&g->session, sp, s, _global);
579 return;
581 sp = MPLS_LIST_NEXT(&g->session, sp, _global);
583 MPLS_LIST_ADD_TAIL(&g->session, s, _global, ldp_session);
586 void _ldp_global_del_session(ldp_global * g, ldp_session * s)
588 MPLS_ASSERT(g && s);
589 MPLS_ASSERT(s->on_global == MPLS_BOOL_TRUE);
590 MPLS_LIST_REMOVE(&g->session, s, _global);
591 s->on_global = MPLS_BOOL_FALSE;
592 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
595 mpls_return_enum _ldp_global_add_inlabel(ldp_global * g, ldp_inlabel * i)
597 ldp_inlabel *ip = NULL;
598 mpls_return_enum result;
600 MPLS_ASSERT(g && i);
602 #if MPLS_USE_LSR
604 lsr_insegment iseg;
605 memcpy(&iseg.info,&i->info,sizeof(mpls_insegment));
606 result = lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_ADD|
607 LSR_INSEGMENT_CFG_NPOP|LSR_INSEGMENT_CFG_FAMILY|
608 LSR_INSEGMENT_CFG_LABELSPACE|LSR_INSEGMENT_CFG_LABEL|
609 LSR_INSEGMENT_CFG_OWNER);
610 memcpy(&i->info, &iseg.info, sizeof(mpls_insegment));
611 i->info.handle = iseg.index;
613 #else
614 result = mpls_mpls_insegment_add(g->mpls_handle, &i->info);
615 #endif
616 if (result != MPLS_SUCCESS) {
617 return result;
620 MPLS_REFCNT_HOLD(i);
621 ip = MPLS_LIST_HEAD(&g->inlabel);
622 while (ip != NULL) {
623 if (ip->index > i->index) {
624 MPLS_LIST_INSERT_BEFORE(&g->inlabel, ip, i, _global);
625 return MPLS_SUCCESS;
627 ip = MPLS_LIST_NEXT(&g->inlabel, ip, _global);
629 MPLS_LIST_ADD_TAIL(&g->inlabel, i, _global, ldp_inlabel);
630 return MPLS_SUCCESS;
633 mpls_return_enum _ldp_global_del_inlabel(ldp_global * g, ldp_inlabel * i)
635 MPLS_ASSERT(g && i);
636 MPLS_ASSERT(i->reuse_count == 0);
637 #if MPLS_USE_LSR
639 lsr_insegment iseg;
640 iseg.index = i->info.handle;
641 lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_DEL);
643 #else
644 mpls_mpls_insegment_del(g->mpls_handle, &i->info);
645 #endif
646 MPLS_LIST_REMOVE(&g->inlabel, i, _global);
647 MPLS_REFCNT_RELEASE(i, ldp_inlabel_delete);
648 return MPLS_SUCCESS;
651 mpls_return_enum _ldp_global_add_outlabel(ldp_global * g, ldp_outlabel * o)
653 ldp_outlabel *op = NULL;
654 mpls_return_enum result;
656 MPLS_ASSERT(g && o);
657 #if MPLS_USE_LSR
659 lsr_outsegment oseg;
660 memcpy(&oseg.info, &o->info, sizeof(mpls_outsegment));
661 result = lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_ADD|
662 LSR_OUTSEGMENT_CFG_PUSH_LABEL|LSR_OUTSEGMENT_CFG_OWNER|
663 LSR_OUTSEGMENT_CFG_INTERFACE|LSR_OUTSEGMENT_CFG_LABEL|
664 LSR_OUTSEGMENT_CFG_NEXTHOP);
665 o->info.handle = oseg.index;
667 #else
668 result = mpls_mpls_outsegment_add(g->mpls_handle, &o->info);
669 #endif
671 if (result != MPLS_SUCCESS) {
672 return result;
675 MPLS_REFCNT_HOLD(o);
676 o->switching = MPLS_BOOL_TRUE;
677 op = MPLS_LIST_HEAD(&g->outlabel);
678 while (op != NULL) {
679 if (op->index > o->index) {
680 MPLS_LIST_INSERT_BEFORE(&g->outlabel, op, o, _global);
681 return MPLS_SUCCESS;
683 op = MPLS_LIST_NEXT(&g->outlabel, op, _global);
685 MPLS_LIST_ADD_TAIL(&g->outlabel, o, _global, ldp_outlabel);
686 return MPLS_SUCCESS;
689 mpls_return_enum _ldp_global_del_outlabel(ldp_global * g, ldp_outlabel * o)
691 MPLS_ASSERT(g && o);
692 #if MPLS_USE_LSR
694 lsr_outsegment oseg;
695 oseg.index = o->info.handle;
696 lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_DEL);
698 #else
699 mpls_mpls_outsegment_del(g->mpls_handle, &o->info);
700 #endif
702 o->switching = MPLS_BOOL_FALSE;
703 MPLS_ASSERT(o->merge_count == 0);
704 MPLS_LIST_REMOVE(&g->outlabel, o, _global);
705 MPLS_REFCNT_RELEASE(o, ldp_outlabel_delete);
706 return MPLS_SUCCESS;
709 mpls_return_enum ldp_global_find_attr_index(ldp_global * g, uint32_t index,
710 ldp_attr ** attr)
712 ldp_attr *a = NULL;
714 if (g && index > 0) {
716 /* because we sort our inserts by index, this lets us know
717 if we've "walked" past the end of the list */
719 a = MPLS_LIST_TAIL(&g->attr);
720 if (a == NULL || a->index < index) {
721 return MPLS_END_OF_LIST;
722 *attr = NULL;
725 a = MPLS_LIST_HEAD(&g->attr);
726 while (a != NULL) {
727 if (a->index == index) {
728 *attr = a;
729 return MPLS_SUCCESS;
731 a = MPLS_LIST_NEXT(&g->attr, a, _global);
734 *attr = NULL;
735 return MPLS_FAILURE;
738 mpls_return_enum ldp_global_find_session_index(ldp_global * g, uint32_t index,
739 ldp_session ** session)
741 ldp_session *s = NULL;
743 if (g && index > 0) {
745 /* because we sort our inserts by index, this lets us know
746 if we've "walked" past the end of the list */
748 s = MPLS_LIST_TAIL(&g->session);
749 if (s == NULL || s->index < index) {
750 *session = NULL;
751 return MPLS_END_OF_LIST;
754 s = MPLS_LIST_HEAD(&g->session);
755 while (s != NULL) {
756 if (s->index == index) {
757 *session = s;
758 return MPLS_SUCCESS;
760 s = MPLS_LIST_NEXT(&g->session, s, _global);
763 *session = NULL;
764 return MPLS_FAILURE;
767 mpls_return_enum ldp_global_find_inlabel_index(ldp_global * g, uint32_t index,
768 ldp_inlabel ** inlabel)
770 ldp_inlabel *i = NULL;
772 if (g && index > 0) {
774 /* because we sort our inserts by index, this lets us know
775 if we've "walked" past the end of the list */
777 i = MPLS_LIST_TAIL(&g->inlabel);
778 if (i == NULL || i->index < index) {
779 *inlabel = NULL;
780 return MPLS_END_OF_LIST;
783 i = MPLS_LIST_HEAD(&g->inlabel);
784 while (i != NULL) {
785 if (i->index == index) {
786 *inlabel = i;
787 return MPLS_SUCCESS;
789 i = MPLS_LIST_NEXT(&g->inlabel, i, _global);
792 *inlabel = NULL;
793 return MPLS_FAILURE;
796 mpls_return_enum ldp_global_find_outlabel_index(ldp_global * g, uint32_t index,
797 ldp_outlabel ** outlabel)
799 ldp_outlabel *o = NULL;
801 if (g && index > 0) {
803 /* because we sort our inserts by index, this lets us know
804 if we've "walked" past the end of the list */
806 o = MPLS_LIST_TAIL(&g->outlabel);
807 if (o == NULL || o->index < index) {
808 *outlabel = NULL;
809 return MPLS_END_OF_LIST;
812 o = MPLS_LIST_HEAD(&g->outlabel);
813 while (o != NULL) {
814 if (o->index == index) {
815 *outlabel = o;
816 return MPLS_SUCCESS;
818 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
821 *outlabel = NULL;
822 return MPLS_FAILURE;
825 ldp_outlabel *ldp_global_find_outlabel_handle(ldp_global * g,
826 mpls_outsegment_handle handle)
828 ldp_outlabel *o = MPLS_LIST_HEAD(&g->outlabel);
830 if (g) {
831 while (o != NULL) {
832 if (!mpls_outsegment_handle_compare(o->info.handle, handle))
833 return o;
835 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
838 return NULL;
841 mpls_return_enum ldp_global_find_entity_index(ldp_global * g, uint32_t index,
842 ldp_entity ** entity)
844 ldp_entity *e = NULL;
846 if (g && index > 0) {
848 /* because we sort our inserts by index, this lets us know
849 if we've "walked" past the end of the list */
851 e = MPLS_LIST_TAIL(&g->entity);
852 if (e == NULL || e->index < index) {
853 *entity = NULL;
854 return MPLS_END_OF_LIST;
857 e = MPLS_LIST_HEAD(&g->entity);
858 while (e != NULL) {
859 if (e->index == index) {
860 *entity = e;
861 return MPLS_SUCCESS;
863 e = MPLS_LIST_NEXT(&g->entity, e, _global);
866 *entity = NULL;
867 return MPLS_FAILURE;
870 ldp_peer *ldp_global_find_peer_addr(ldp_global * g, mpls_inet_addr * addr)
872 ldp_peer *p;
874 MPLS_ASSERT(g && addr);
876 /* JLEU: we will need to add a tree to optimize this search,
877 known peers will be in tree, unknown will take a "slow path" to
878 verify them, then be added to tree */
880 p = MPLS_LIST_HEAD(&g->peer);
881 while (p) {
882 LDP_PRINT(g->user_data,
883 "ldp_global_find_peer_lsrid: peer: %08x lsrid: %08x\n",
884 p->dest.addr.u.ipv4, addr->u.ipv4);
885 if (!mpls_inet_addr_compare(&p->dest.addr, addr)) {
886 return p;
888 p = MPLS_LIST_NEXT(&g->peer, p, _global);
890 return NULL;
893 mpls_return_enum ldp_global_find_adj_index(ldp_global * g, uint32_t index,
894 ldp_adj ** adj)
896 ldp_adj *a = NULL;
898 if (g && index > 0) {
899 /* because we sort our inserts by index, this lets us know
900 if we've "walked" past the end of the list */
902 a = MPLS_LIST_TAIL(&g->adj);
903 if (a == NULL || a->index < index) {
904 return MPLS_END_OF_LIST;
905 *adj = NULL;
908 a = MPLS_LIST_HEAD(&g->adj);
909 while (a != NULL) {
910 if (a->index == index) {
911 *adj = a;
912 return MPLS_SUCCESS;
914 a = MPLS_LIST_NEXT(&g->adj, a, _global);
917 *adj = NULL;
918 return MPLS_FAILURE;
921 mpls_return_enum ldp_global_find_peer_index(ldp_global * g, uint32_t index,
922 ldp_peer ** peer)
924 ldp_peer *p = NULL;
926 if (g && index > 0) {
927 /* because we sort our inserts by index, this lets us know
928 if we've "walked" past the end of the list */
930 p = MPLS_LIST_TAIL(&g->peer);
931 if (p == NULL || p->index < index) {
932 *peer = NULL;
933 return MPLS_END_OF_LIST;
936 p = MPLS_LIST_HEAD(&g->peer);
937 while (p != NULL) {
938 if (p->index == index) {
939 *peer = p;
940 return MPLS_SUCCESS;
942 p = MPLS_LIST_NEXT(&g->peer, p, _global);
945 *peer = NULL;
946 return MPLS_FAILURE;
949 mpls_return_enum ldp_global_find_fec_index(ldp_global * g, uint32_t index,
950 ldp_fec ** fec)
952 ldp_fec *f = NULL;
954 if (g && index > 0) {
955 /* because we sort our inserts by index, this lets us know
956 if we've "walked" past the end of the list */
958 f = MPLS_LIST_TAIL(&g->fec);
959 if (f == NULL || f->index < index) {
960 *fec = NULL;
961 return MPLS_END_OF_LIST;
964 f = MPLS_LIST_HEAD(&g->fec);
965 while (f != NULL) {
966 if (f->index == index) {
967 *fec = f;
968 return MPLS_SUCCESS;
970 f = MPLS_LIST_NEXT(&g->fec, f, _global);
973 *fec = NULL;
974 return MPLS_FAILURE;
977 mpls_return_enum ldp_global_find_fec(ldp_global * g, mpls_fec * m,
978 ldp_fec ** fec)
980 ldp_fec *f = NULL;
982 MPLS_ASSERT(g && m);
984 f = MPLS_LIST_HEAD(&g->fec);
985 do {
986 if (!mpls_fec_compare(m, &f->info)) {
987 *fec = f;
988 return MPLS_SUCCESS;
990 } while((f = MPLS_LIST_NEXT(&g->fec, f, _global)));
991 *fec = NULL;
992 return MPLS_FAILURE;
995 mpls_return_enum ldp_global_find_addr_index(ldp_global * g, uint32_t index,
996 ldp_addr ** addr)
998 ldp_addr *a = NULL;
1000 if (g && index > 0) {
1002 /* because we sort our inserts by index, this lets us know
1003 if we've "walked" past the end of the list */
1005 a = MPLS_LIST_TAIL(&g->addr);
1006 if (a == NULL || a->index < index) {
1007 *addr = NULL;
1008 return MPLS_END_OF_LIST;
1011 a = MPLS_LIST_HEAD(&g->addr);
1012 while (a != NULL) {
1013 if (a->index == index) {
1014 *addr = a;
1015 return MPLS_SUCCESS;
1017 a = MPLS_LIST_NEXT(&g->addr, a, _global);
1020 *addr = NULL;
1021 return MPLS_FAILURE;
1024 mpls_return_enum ldp_global_find_if_index(ldp_global * g, uint32_t index,
1025 ldp_if ** iff)
1027 ldp_if *i = NULL;
1029 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 i = MPLS_LIST_TAIL(&g->iff);
1035 if (i == NULL || i->index < index) {
1036 *iff = NULL;
1037 return MPLS_END_OF_LIST;
1040 i = MPLS_LIST_HEAD(&g->iff);
1041 while (i != NULL) {
1042 if (i->index == index) {
1043 *iff = i;
1044 return MPLS_SUCCESS;
1046 i = MPLS_LIST_NEXT(&g->iff, i, _global);
1049 *iff = NULL;
1050 return MPLS_FAILURE;
1053 ldp_if *ldp_global_find_if_handle(ldp_global * g, mpls_if_handle handle)
1055 ldp_if *i = MPLS_LIST_HEAD(&g->iff);
1057 if (g) {
1058 while (i != NULL) {
1059 if (!mpls_if_handle_compare(i->handle, handle))
1060 return i;
1062 i = MPLS_LIST_NEXT(&g->iff, i, _global);
1065 return NULL;
1068 ldp_adj *ldp_global_find_adj_ldpid(ldp_global * g, mpls_inet_addr * lsraddr,
1069 int labelspace)
1072 ldp_adj *a = MPLS_LIST_HEAD(&g->adj);
1074 while (a != NULL) {
1075 if ((!mpls_inet_addr_compare(lsraddr, &a->remote_lsr_address)) &&
1076 labelspace == a->remote_label_space)
1077 return a;
1079 a = MPLS_LIST_NEXT(&g->adj, a, _global);
1081 return NULL;
1084 mpls_return_enum ldp_global_find_tunnel_index(ldp_global * g, uint32_t index,
1085 ldp_tunnel ** tunnel)
1087 ldp_tunnel *t = NULL;
1089 if (g && index > 0) {
1090 /* because we sort our inserts by index, this lets us know
1091 if we've "walked" past the end of the list */
1093 t = MPLS_LIST_TAIL(&g->tunnel);
1094 if (t == NULL || t->index < index) {
1095 *tunnel = NULL;
1096 return MPLS_END_OF_LIST;
1099 t = MPLS_LIST_HEAD(&g->tunnel);
1100 while (t != NULL) {
1101 if (t->index == index) {
1102 *tunnel = t;
1103 return MPLS_SUCCESS;
1105 t = MPLS_LIST_NEXT(&g->tunnel, t, _global);
1108 *tunnel = NULL;
1109 return MPLS_FAILURE;
1112 mpls_return_enum ldp_global_find_resource_index(ldp_global * g, uint32_t index,
1113 ldp_resource ** resource)
1115 ldp_resource *r = NULL;
1117 if (g && index > 0) {
1118 /* because we sort our inserts by index, this lets us know
1119 if we've "walked" past the end of the list */
1121 r = MPLS_LIST_TAIL(&g->resource);
1122 if (r == NULL || r->index < index) {
1123 *resource = NULL;
1124 return MPLS_END_OF_LIST;
1127 r = MPLS_LIST_HEAD(&g->resource);
1128 while (r != NULL) {
1129 if (r->index == index) {
1130 *resource = r;
1131 return MPLS_SUCCESS;
1133 r = MPLS_LIST_NEXT(&g->resource, r, _global);
1136 *resource = NULL;
1137 return MPLS_FAILURE;
1140 mpls_return_enum ldp_global_find_hop_list_index(ldp_global * g, uint32_t index,
1141 ldp_hop_list ** hop_list)
1143 ldp_hop_list *h = NULL;
1145 if (g && index > 0) {
1146 /* because we sort our inserts by index, this lets us know
1147 if we've "walked" past the end of the list */
1149 h = MPLS_LIST_TAIL(&g->hop_list);
1150 if (h == NULL || h->index < index) {
1151 *hop_list = NULL;
1152 return MPLS_END_OF_LIST;
1155 h = MPLS_LIST_HEAD(&g->hop_list);
1156 while (h != NULL) {
1157 if (h->index == index) {
1158 *hop_list = h;
1159 return MPLS_SUCCESS;
1161 h = MPLS_LIST_NEXT(&g->hop_list, h, _global);
1164 *hop_list = NULL;
1165 return MPLS_FAILURE;
1168 void _ldp_global_add_tunnel(ldp_global * g, ldp_tunnel * t)
1170 ldp_tunnel *tp = NULL;
1172 MPLS_ASSERT(g && t);
1173 MPLS_REFCNT_HOLD(t);
1174 tp = MPLS_LIST_HEAD(&g->tunnel);
1175 while (tp != NULL) {
1176 if (tp->index > t->index) {
1177 MPLS_LIST_INSERT_BEFORE(&g->tunnel, tp, t, _global);
1178 return;
1180 tp = MPLS_LIST_NEXT(&g->tunnel, tp, _global);
1182 MPLS_LIST_ADD_TAIL(&g->tunnel, t, _global, ldp_tunnel);
1185 void _ldp_global_del_tunnel(ldp_global * g, ldp_tunnel * t)
1187 MPLS_ASSERT(g && t);
1188 MPLS_LIST_REMOVE(&g->tunnel, t, _global);
1189 MPLS_REFCNT_RELEASE(t, ldp_tunnel_delete);
1192 void _ldp_global_add_resource(ldp_global * g, ldp_resource * r)
1194 ldp_resource *rp = NULL;
1196 MPLS_ASSERT(g && r);
1197 MPLS_REFCNT_HOLD(r);
1198 rp = MPLS_LIST_HEAD(&g->resource);
1199 while (rp != NULL) {
1200 if (rp->index > r->index) {
1201 MPLS_LIST_INSERT_BEFORE(&g->resource, rp, r, _global);
1202 return;
1204 rp = MPLS_LIST_NEXT(&g->resource, rp, _global);
1206 MPLS_LIST_ADD_TAIL(&g->resource, r, _global, ldp_resource);
1209 void _ldp_global_del_resource(ldp_global * g, ldp_resource * r)
1211 MPLS_ASSERT(g && r);
1212 MPLS_LIST_REMOVE(&g->resource, r, _global);
1213 MPLS_REFCNT_RELEASE(r, ldp_resource_delete);
1216 void _ldp_global_add_hop_list(ldp_global * g, ldp_hop_list * h)
1218 ldp_hop_list *hp = NULL;
1220 MPLS_ASSERT(g && h);
1221 MPLS_REFCNT_HOLD(h);
1222 hp = MPLS_LIST_HEAD(&g->hop_list);
1223 while (hp != NULL) {
1224 if (hp->index > h->index) {
1225 MPLS_LIST_INSERT_BEFORE(&g->hop_list, hp, h, _global);
1226 return;
1228 hp = MPLS_LIST_NEXT(&g->hop_list, hp, _global);
1230 MPLS_LIST_ADD_TAIL(&g->hop_list, h, _global, ldp_hop_list);
1233 void _ldp_global_del_hop_list(ldp_global * g, ldp_hop_list * h)
1235 MPLS_ASSERT(g && h);
1236 MPLS_LIST_REMOVE(&g->hop_list, h, _global);
1237 MPLS_REFCNT_RELEASE(h, ldp_hop_list_delete);
1240 void _ldp_global_add_fec(ldp_global * g, ldp_fec * f)
1242 ldp_fec *fp = NULL;
1244 MPLS_ASSERT(g && f);
1245 MPLS_REFCNT_HOLD(f);
1246 fp = MPLS_LIST_HEAD(&g->fec);
1247 while (fp != NULL) {
1248 if (fp->index > f->index) {
1249 MPLS_LIST_INSERT_BEFORE(&g->fec, fp, f, _global);
1250 return;
1252 fp = MPLS_LIST_NEXT(&g->fec, fp, _global);
1254 MPLS_LIST_ADD_TAIL(&g->fec, f, _global, ldp_fec);
1257 void _ldp_global_del_fec(ldp_global * g, ldp_fec * f)
1259 MPLS_ASSERT(g && f);
1260 MPLS_LIST_REMOVE(&g->fec, f, _global);
1261 MPLS_REFCNT_RELEASE(f, ldp_fec_delete);
1264 void _ldp_global_add_nexthop(ldp_global * g, ldp_nexthop * nh)
1266 ldp_nexthop *nhp = NULL;
1268 MPLS_ASSERT(g && nh);
1269 MPLS_REFCNT_HOLD(nh);
1270 nhp = MPLS_LIST_HEAD(&g->nexthop);
1271 while (nhp != NULL) {
1272 if (nhp->index > nh->index) {
1273 MPLS_LIST_INSERT_BEFORE(&g->nexthop, nhp, nh, _global);
1274 return;
1276 nhp = MPLS_LIST_NEXT(&g->nexthop, nhp, _global);
1278 MPLS_LIST_ADD_TAIL(&g->nexthop, nh, _global, ldp_nexthop);
1281 void _ldp_global_del_nexthop(ldp_global * g, ldp_nexthop * nh)
1283 MPLS_ASSERT(g && nh);
1284 MPLS_LIST_REMOVE(&g->nexthop, nh, _global);
1285 MPLS_REFCNT_RELEASE(nh, ldp_nexthop_delete);