FECs are now added to the global list as part of creation, and
[mpls-ldp-portable.git] / ldp / ldp_global.c
bloba959ef7a9c96931ff4197998a9eb7acffb5a5f78
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);
299 if (!f) {
300 goto ldp_global_startup_cleanup;
303 n = ldp_nexthop_create();
304 if (!n) {
305 goto ldp_global_startup_cleanup;
308 memcpy(&n->info, &nexthop, sizeof(mpls_nexthop));
309 n->type = nexthop.type;
310 if (ldp_fec_add_nexthop(g, f, n) != MPLS_SUCCESS) {
311 goto ldp_global_startup_cleanup;
313 _ldp_global_add_nexthop(g, n);
314 } while (mpls_fib_getnext_route(g->fib_handle, &fec, &nexthop) ==
315 MPLS_SUCCESS);
319 e = MPLS_LIST_HEAD(&g->entity);
320 while (e != NULL) {
321 ldp_entity_startup(g, e);
322 e = MPLS_LIST_NEXT(&g->entity, e, _global);
325 g->admin_state = MPLS_ADMIN_ENABLE;
327 LDP_EXIT(g->user_data, "ldp_global_startup");
328 return MPLS_SUCCESS;
330 ldp_global_startup_cleanup:
331 ldp_global_shutdown(g);
332 mpls_socket_close(g->socket_handle, g->hello_socket);
333 mpls_socket_close(g->socket_handle, g->listen_socket);
334 g->hello_socket = 0;
335 g->listen_socket = 0;
337 LDP_EXIT(g->user_data, "ldp_global_startup-error");
339 return MPLS_FAILURE;
342 mpls_return_enum ldp_global_shutdown(ldp_global * g)
344 ldp_entity *e = NULL;
346 MPLS_ASSERT(g);
348 LDP_ENTER(g->user_data, "ldp_global_shutdown");
350 e = MPLS_LIST_HEAD(&g->entity);
351 while (e != NULL) {
352 ldp_entity_shutdown(g, e, 1);
353 e = MPLS_LIST_NEXT(&g->entity, e, _global);
356 g->admin_state = MPLS_ADMIN_DISABLE;
359 ldp_nexthop *n;
360 ldp_fec *f;
361 while ((f = MPLS_LIST_HEAD(&g->fec))) {
362 while ((n = MPLS_LIST_HEAD(&f->nh_root))) {
363 ldp_fec_del_nexthop(g, f, n);
368 ldp_addr *a;
369 ldp_if *i;
370 while ((i = MPLS_LIST_HEAD(&g->iff))) {
371 while ((a = MPLS_LIST_HEAD(&i->addr_root))) {
372 ldp_if_del_addr(g, i, a);
374 ldp_if_remove(g, i);
378 mpls_socket_readlist_del(g->socket_handle, g->hello_socket);
379 mpls_socket_close(g->socket_handle, g->hello_socket);
381 mpls_socket_readlist_del(g->socket_handle, g->listen_socket);
382 mpls_socket_close(g->socket_handle, g->listen_socket);
384 mpls_tree_delete(g->addr_tree);
385 mpls_tree_delete(g->fec_tree);
387 mpls_lock_release(g->global_lock);
388 mpls_timer_close(g->timer_handle);
389 mpls_lock_get(g->global_lock);
391 mpls_socket_mgr_close(g->socket_handle);
392 mpls_ifmgr_close(g->ifmgr_handle);
393 mpls_fib_close(g->fib_handle);
395 #if MPLS_USE_LSR
396 #else
397 mpls_mpls_close(g->mpls_handle);
398 #endif
400 LDP_EXIT(g->user_data, "ldp_global_shutdown");
402 return MPLS_SUCCESS;
405 mpls_return_enum ldp_global_delete(ldp_global * g)
407 if (g) {
408 mpls_lock_delete(g->global_lock);
409 LDP_PRINT(g->user_data, "global delete\n");
410 mpls_free(g);
412 return MPLS_SUCCESS;
415 void _ldp_global_add_attr(ldp_global * g, ldp_attr * a)
417 ldp_attr *ap = NULL;
419 MPLS_ASSERT(g && a);
420 MPLS_REFCNT_HOLD(a);
421 ap = MPLS_LIST_HEAD(&g->attr);
422 while (ap != NULL) {
423 if (ap->index > a->index) {
424 MPLS_LIST_INSERT_BEFORE(&g->attr, ap, a, _global);
425 return;
427 ap = MPLS_LIST_NEXT(&g->attr, ap, _global);
429 MPLS_LIST_ADD_TAIL(&g->attr, a, _global, ldp_attr);
432 void _ldp_global_del_attr(ldp_global * g, ldp_attr * a)
434 MPLS_ASSERT(g && a);
435 MPLS_LIST_REMOVE(&g->attr, a, _global);
436 MPLS_REFCNT_RELEASE(a, ldp_attr_delete);
439 void _ldp_global_add_peer(ldp_global * g, ldp_peer * p)
441 ldp_peer *pp = NULL;
443 MPLS_ASSERT(g && p);
444 MPLS_REFCNT_HOLD(p);
445 pp = MPLS_LIST_HEAD(&g->peer);
446 while (pp != NULL) {
447 if (pp->index > p->index) {
448 MPLS_LIST_INSERT_BEFORE(&g->peer, pp, p, _global);
449 return;
451 pp = MPLS_LIST_NEXT(&g->peer, pp, _global);
453 MPLS_LIST_ADD_TAIL(&g->peer, p, _global, ldp_peer);
456 void _ldp_global_del_peer(ldp_global * g, ldp_peer * p)
458 MPLS_ASSERT(g && p);
459 MPLS_LIST_REMOVE(&g->peer, p, _global);
460 MPLS_REFCNT_RELEASE(p, ldp_peer_delete);
464 * _ldp_global_add_if/del_if and _ldp_global_add_addr/del_addr are
465 * not the same as the rest of the global_add/del functions. They
466 * do not hold refcnts, they are used as part of the create and delete
467 * process of these structures
470 void _ldp_global_add_if(ldp_global * g, ldp_if * i)
472 ldp_if *ip = NULL;
474 MPLS_ASSERT(g && i);
475 ip = MPLS_LIST_HEAD(&g->iff);
476 while (ip != NULL) {
477 if (ip->index > i->index) {
478 MPLS_LIST_INSERT_BEFORE(&g->iff, ip, i, _global);
479 return;
481 ip = MPLS_LIST_NEXT(&g->iff, ip, _global);
483 MPLS_LIST_ADD_TAIL(&g->iff, i, _global, ldp_if);
486 void _ldp_global_del_if(ldp_global * g, ldp_if * i)
488 MPLS_ASSERT(g && i);
489 MPLS_LIST_REMOVE(&g->iff, i, _global);
492 void _ldp_global_add_addr(ldp_global * g, ldp_addr * a)
494 ldp_addr *ap = NULL;
496 MPLS_ASSERT(g && a);
497 ap = MPLS_LIST_HEAD(&g->addr);
498 while (ap != NULL) {
499 if (ap->index > a->index) {
500 MPLS_LIST_INSERT_BEFORE(&g->addr, ap, a, _global);
501 return;
503 ap = MPLS_LIST_NEXT(&g->addr, ap, _global);
505 MPLS_LIST_ADD_TAIL(&g->addr, a, _global, ldp_addr);
508 void _ldp_global_del_addr(ldp_global * g, ldp_addr * a)
510 MPLS_ASSERT(g && a);
511 MPLS_LIST_REMOVE(&g->addr, a, _global);
516 void _ldp_global_add_adj(ldp_global * g, ldp_adj * a)
518 ldp_adj *ap = NULL;
520 MPLS_ASSERT(g && a);
521 MPLS_REFCNT_HOLD(a);
522 ap = MPLS_LIST_HEAD(&g->adj);
523 while (ap != NULL) {
524 if (ap->index > a->index) {
525 MPLS_LIST_INSERT_BEFORE(&g->adj, ap, a, _global);
526 return;
528 ap = MPLS_LIST_NEXT(&g->adj, ap, _global);
530 MPLS_LIST_ADD_TAIL(&g->adj, a, _global, ldp_adj);
533 void _ldp_global_del_adj(ldp_global * g, ldp_adj * a)
535 MPLS_ASSERT(g && a);
536 MPLS_LIST_REMOVE(&g->adj, a, _global);
537 MPLS_REFCNT_RELEASE(a, ldp_adj_delete);
540 void _ldp_global_add_entity(ldp_global * g, ldp_entity * e)
542 ldp_entity *ep = NULL;
544 MPLS_ASSERT(g && e);
545 MPLS_REFCNT_HOLD(e);
546 ep = MPLS_LIST_HEAD(&g->entity);
547 while (ep != NULL) {
548 if (ep->index > e->index) {
549 MPLS_LIST_INSERT_BEFORE(&g->entity, ep, e, _global);
550 return;
552 ep = MPLS_LIST_NEXT(&g->entity, ep, _global);
554 MPLS_LIST_ADD_TAIL(&g->entity, e, _global, ldp_entity);
557 void _ldp_global_del_entity(ldp_global * g, ldp_entity * e)
559 MPLS_ASSERT(g && e);
560 MPLS_LIST_REMOVE(&g->entity, e, _global);
561 MPLS_REFCNT_RELEASE(e, ldp_entity_delete);
564 void _ldp_global_add_session(ldp_global * g, ldp_session * s)
566 ldp_session *sp = NULL;
568 MPLS_ASSERT(g && s);
569 MPLS_REFCNT_HOLD(s);
570 s->on_global = MPLS_BOOL_TRUE;
571 sp = MPLS_LIST_HEAD(&g->session);
572 while (sp != NULL) {
573 if (sp->index > s->index) {
574 MPLS_LIST_INSERT_BEFORE(&g->session, sp, s, _global);
575 return;
577 sp = MPLS_LIST_NEXT(&g->session, sp, _global);
579 MPLS_LIST_ADD_TAIL(&g->session, s, _global, ldp_session);
582 void _ldp_global_del_session(ldp_global * g, ldp_session * s)
584 MPLS_ASSERT(g && s);
585 MPLS_ASSERT(s->on_global == MPLS_BOOL_TRUE);
586 MPLS_LIST_REMOVE(&g->session, s, _global);
587 s->on_global = MPLS_BOOL_FALSE;
588 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
591 mpls_return_enum _ldp_global_add_inlabel(ldp_global * g, ldp_inlabel * i)
593 ldp_inlabel *ip = NULL;
594 mpls_return_enum result;
596 MPLS_ASSERT(g && i);
598 #if MPLS_USE_LSR
600 lsr_insegment iseg;
601 memcpy(&iseg.info,&i->info,sizeof(mpls_insegment));
602 result = lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_ADD|
603 LSR_INSEGMENT_CFG_NPOP|LSR_INSEGMENT_CFG_FAMILY|
604 LSR_INSEGMENT_CFG_LABELSPACE|LSR_INSEGMENT_CFG_LABEL|
605 LSR_INSEGMENT_CFG_OWNER);
606 memcpy(&i->info, &iseg.info, sizeof(mpls_insegment));
607 i->info.handle = iseg.index;
609 #else
610 result = mpls_mpls_insegment_add(g->mpls_handle, &i->info);
611 #endif
612 if (result != MPLS_SUCCESS) {
613 return result;
616 MPLS_REFCNT_HOLD(i);
617 ip = MPLS_LIST_HEAD(&g->inlabel);
618 while (ip != NULL) {
619 if (ip->index > i->index) {
620 MPLS_LIST_INSERT_BEFORE(&g->inlabel, ip, i, _global);
621 return MPLS_SUCCESS;
623 ip = MPLS_LIST_NEXT(&g->inlabel, ip, _global);
625 MPLS_LIST_ADD_TAIL(&g->inlabel, i, _global, ldp_inlabel);
626 return MPLS_SUCCESS;
629 mpls_return_enum _ldp_global_del_inlabel(ldp_global * g, ldp_inlabel * i)
631 MPLS_ASSERT(g && i);
632 MPLS_ASSERT(i->reuse_count == 0);
633 #if MPLS_USE_LSR
635 lsr_insegment iseg;
636 iseg.index = i->info.handle;
637 lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_DEL);
639 #else
640 mpls_mpls_insegment_del(g->mpls_handle, &i->info);
641 #endif
642 MPLS_LIST_REMOVE(&g->inlabel, i, _global);
643 MPLS_REFCNT_RELEASE(i, ldp_inlabel_delete);
644 return MPLS_SUCCESS;
647 mpls_return_enum _ldp_global_add_outlabel(ldp_global * g, ldp_outlabel * o)
649 ldp_outlabel *op = NULL;
650 mpls_return_enum result;
652 MPLS_ASSERT(g && o);
653 #if MPLS_USE_LSR
655 lsr_outsegment oseg;
656 memcpy(&oseg.info, &o->info, sizeof(mpls_outsegment));
657 result = lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_ADD|
658 LSR_OUTSEGMENT_CFG_PUSH_LABEL|LSR_OUTSEGMENT_CFG_OWNER|
659 LSR_OUTSEGMENT_CFG_INTERFACE|LSR_OUTSEGMENT_CFG_LABEL|
660 LSR_OUTSEGMENT_CFG_NEXTHOP);
661 o->info.handle = oseg.index;
663 #else
664 result = mpls_mpls_outsegment_add(g->mpls_handle, &o->info);
665 #endif
667 if (result != MPLS_SUCCESS) {
668 return result;
671 MPLS_REFCNT_HOLD(o);
672 o->switching = MPLS_BOOL_TRUE;
673 op = MPLS_LIST_HEAD(&g->outlabel);
674 while (op != NULL) {
675 if (op->index > o->index) {
676 MPLS_LIST_INSERT_BEFORE(&g->outlabel, op, o, _global);
677 return MPLS_SUCCESS;
679 op = MPLS_LIST_NEXT(&g->outlabel, op, _global);
681 MPLS_LIST_ADD_TAIL(&g->outlabel, o, _global, ldp_outlabel);
682 return MPLS_SUCCESS;
685 mpls_return_enum _ldp_global_del_outlabel(ldp_global * g, ldp_outlabel * o)
687 MPLS_ASSERT(g && o);
688 #if MPLS_USE_LSR
690 lsr_outsegment oseg;
691 oseg.index = o->info.handle;
692 lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_DEL);
694 #else
695 mpls_mpls_outsegment_del(g->mpls_handle, &o->info);
696 #endif
698 o->switching = MPLS_BOOL_FALSE;
699 MPLS_ASSERT(o->merge_count == 0);
700 MPLS_LIST_REMOVE(&g->outlabel, o, _global);
701 MPLS_REFCNT_RELEASE(o, ldp_outlabel_delete);
702 return MPLS_SUCCESS;
705 mpls_return_enum ldp_global_find_attr_index(ldp_global * g, uint32_t index,
706 ldp_attr ** attr)
708 ldp_attr *a = NULL;
710 if (g && index > 0) {
712 /* because we sort our inserts by index, this lets us know
713 if we've "walked" past the end of the list */
715 a = MPLS_LIST_TAIL(&g->attr);
716 if (a == NULL || a->index < index) {
717 return MPLS_END_OF_LIST;
718 *attr = NULL;
721 a = MPLS_LIST_HEAD(&g->attr);
722 while (a != NULL) {
723 if (a->index == index) {
724 *attr = a;
725 return MPLS_SUCCESS;
727 a = MPLS_LIST_NEXT(&g->attr, a, _global);
730 *attr = NULL;
731 return MPLS_FAILURE;
734 mpls_return_enum ldp_global_find_session_index(ldp_global * g, uint32_t index,
735 ldp_session ** session)
737 ldp_session *s = NULL;
739 if (g && index > 0) {
741 /* because we sort our inserts by index, this lets us know
742 if we've "walked" past the end of the list */
744 s = MPLS_LIST_TAIL(&g->session);
745 if (s == NULL || s->index < index) {
746 *session = NULL;
747 return MPLS_END_OF_LIST;
750 s = MPLS_LIST_HEAD(&g->session);
751 while (s != NULL) {
752 if (s->index == index) {
753 *session = s;
754 return MPLS_SUCCESS;
756 s = MPLS_LIST_NEXT(&g->session, s, _global);
759 *session = NULL;
760 return MPLS_FAILURE;
763 mpls_return_enum ldp_global_find_inlabel_index(ldp_global * g, uint32_t index,
764 ldp_inlabel ** inlabel)
766 ldp_inlabel *i = NULL;
768 if (g && index > 0) {
770 /* because we sort our inserts by index, this lets us know
771 if we've "walked" past the end of the list */
773 i = MPLS_LIST_TAIL(&g->inlabel);
774 if (i == NULL || i->index < index) {
775 *inlabel = NULL;
776 return MPLS_END_OF_LIST;
779 i = MPLS_LIST_HEAD(&g->inlabel);
780 while (i != NULL) {
781 if (i->index == index) {
782 *inlabel = i;
783 return MPLS_SUCCESS;
785 i = MPLS_LIST_NEXT(&g->inlabel, i, _global);
788 *inlabel = NULL;
789 return MPLS_FAILURE;
792 mpls_return_enum ldp_global_find_outlabel_index(ldp_global * g, uint32_t index,
793 ldp_outlabel ** outlabel)
795 ldp_outlabel *o = NULL;
797 if (g && index > 0) {
799 /* because we sort our inserts by index, this lets us know
800 if we've "walked" past the end of the list */
802 o = MPLS_LIST_TAIL(&g->outlabel);
803 if (o == NULL || o->index < index) {
804 *outlabel = NULL;
805 return MPLS_END_OF_LIST;
808 o = MPLS_LIST_HEAD(&g->outlabel);
809 while (o != NULL) {
810 if (o->index == index) {
811 *outlabel = o;
812 return MPLS_SUCCESS;
814 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
817 *outlabel = NULL;
818 return MPLS_FAILURE;
821 ldp_outlabel *ldp_global_find_outlabel_handle(ldp_global * g,
822 mpls_outsegment_handle handle)
824 ldp_outlabel *o = MPLS_LIST_HEAD(&g->outlabel);
826 if (g) {
827 while (o != NULL) {
828 if (!mpls_outsegment_handle_compare(o->info.handle, handle))
829 return o;
831 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
834 return NULL;
837 mpls_return_enum ldp_global_find_entity_index(ldp_global * g, uint32_t index,
838 ldp_entity ** entity)
840 ldp_entity *e = NULL;
842 if (g && index > 0) {
844 /* because we sort our inserts by index, this lets us know
845 if we've "walked" past the end of the list */
847 e = MPLS_LIST_TAIL(&g->entity);
848 if (e == NULL || e->index < index) {
849 *entity = NULL;
850 return MPLS_END_OF_LIST;
853 e = MPLS_LIST_HEAD(&g->entity);
854 while (e != NULL) {
855 if (e->index == index) {
856 *entity = e;
857 return MPLS_SUCCESS;
859 e = MPLS_LIST_NEXT(&g->entity, e, _global);
862 *entity = NULL;
863 return MPLS_FAILURE;
866 ldp_peer *ldp_global_find_peer_addr(ldp_global * g, mpls_inet_addr * addr)
868 ldp_peer *p;
870 MPLS_ASSERT(g && addr);
872 /* JLEU: we will need to add a tree to optimize this search,
873 known peers will be in tree, unknown will take a "slow path" to
874 verify them, then be added to tree */
876 p = MPLS_LIST_HEAD(&g->peer);
877 while (p) {
878 LDP_PRINT(g->user_data,
879 "ldp_global_find_peer_lsrid: peer: %08x lsrid: %08x\n",
880 p->dest.addr.u.ipv4, addr->u.ipv4);
881 if (!mpls_inet_addr_compare(&p->dest.addr, addr)) {
882 return p;
884 p = MPLS_LIST_NEXT(&g->peer, p, _global);
886 return NULL;
889 mpls_return_enum ldp_global_find_adj_index(ldp_global * g, uint32_t index,
890 ldp_adj ** adj)
892 ldp_adj *a = NULL;
894 if (g && index > 0) {
895 /* because we sort our inserts by index, this lets us know
896 if we've "walked" past the end of the list */
898 a = MPLS_LIST_TAIL(&g->adj);
899 if (a == NULL || a->index < index) {
900 return MPLS_END_OF_LIST;
901 *adj = NULL;
904 a = MPLS_LIST_HEAD(&g->adj);
905 while (a != NULL) {
906 if (a->index == index) {
907 *adj = a;
908 return MPLS_SUCCESS;
910 a = MPLS_LIST_NEXT(&g->adj, a, _global);
913 *adj = NULL;
914 return MPLS_FAILURE;
917 mpls_return_enum ldp_global_find_peer_index(ldp_global * g, uint32_t index,
918 ldp_peer ** peer)
920 ldp_peer *p = NULL;
922 if (g && index > 0) {
923 /* because we sort our inserts by index, this lets us know
924 if we've "walked" past the end of the list */
926 p = MPLS_LIST_TAIL(&g->peer);
927 if (p == NULL || p->index < index) {
928 *peer = NULL;
929 return MPLS_END_OF_LIST;
932 p = MPLS_LIST_HEAD(&g->peer);
933 while (p != NULL) {
934 if (p->index == index) {
935 *peer = p;
936 return MPLS_SUCCESS;
938 p = MPLS_LIST_NEXT(&g->peer, p, _global);
941 *peer = NULL;
942 return MPLS_FAILURE;
945 mpls_return_enum ldp_global_find_fec_index(ldp_global * g, uint32_t index,
946 ldp_fec ** fec)
948 ldp_fec *f = NULL;
950 if (g && index > 0) {
951 /* because we sort our inserts by index, this lets us know
952 if we've "walked" past the end of the list */
954 f = MPLS_LIST_TAIL(&g->fec);
955 if (f == NULL || f->index < index) {
956 *fec = NULL;
957 return MPLS_END_OF_LIST;
960 f = MPLS_LIST_HEAD(&g->fec);
961 while (f != NULL) {
962 if (f->index == index) {
963 *fec = f;
964 return MPLS_SUCCESS;
966 f = MPLS_LIST_NEXT(&g->fec, f, _global);
969 *fec = NULL;
970 return MPLS_FAILURE;
973 mpls_return_enum ldp_global_find_fec(ldp_global * g, mpls_fec * m,
974 ldp_fec ** fec)
976 ldp_fec *f = NULL;
978 MPLS_ASSERT(g && m);
980 f = MPLS_LIST_HEAD(&g->fec);
981 do {
982 if (!mpls_fec_compare(m, &f->info)) {
983 *fec = f;
984 return MPLS_SUCCESS;
986 } while((f = MPLS_LIST_NEXT(&g->fec, f, _global)));
987 *fec = NULL;
988 return MPLS_FAILURE;
991 mpls_return_enum ldp_global_find_addr_index(ldp_global * g, uint32_t index,
992 ldp_addr ** addr)
994 ldp_addr *a = NULL;
996 if (g && index > 0) {
998 /* because we sort our inserts by index, this lets us know
999 if we've "walked" past the end of the list */
1001 a = MPLS_LIST_TAIL(&g->addr);
1002 if (a == NULL || a->index < index) {
1003 *addr = NULL;
1004 return MPLS_END_OF_LIST;
1007 a = MPLS_LIST_HEAD(&g->addr);
1008 while (a != NULL) {
1009 if (a->index == index) {
1010 *addr = a;
1011 return MPLS_SUCCESS;
1013 a = MPLS_LIST_NEXT(&g->addr, a, _global);
1016 *addr = NULL;
1017 return MPLS_FAILURE;
1020 mpls_return_enum ldp_global_find_if_index(ldp_global * g, uint32_t index,
1021 ldp_if ** iff)
1023 ldp_if *i = NULL;
1025 if (g && index > 0) {
1027 /* because we sort our inserts by index, this lets us know
1028 if we've "walked" past the end of the list */
1030 i = MPLS_LIST_TAIL(&g->iff);
1031 if (i == NULL || i->index < index) {
1032 *iff = NULL;
1033 return MPLS_END_OF_LIST;
1036 i = MPLS_LIST_HEAD(&g->iff);
1037 while (i != NULL) {
1038 if (i->index == index) {
1039 *iff = i;
1040 return MPLS_SUCCESS;
1042 i = MPLS_LIST_NEXT(&g->iff, i, _global);
1045 *iff = NULL;
1046 return MPLS_FAILURE;
1049 ldp_if *ldp_global_find_if_handle(ldp_global * g, mpls_if_handle handle)
1051 ldp_if *i = MPLS_LIST_HEAD(&g->iff);
1053 if (g) {
1054 while (i != NULL) {
1055 if (!mpls_if_handle_compare(i->handle, handle))
1056 return i;
1058 i = MPLS_LIST_NEXT(&g->iff, i, _global);
1061 return NULL;
1064 ldp_adj *ldp_global_find_adj_ldpid(ldp_global * g, mpls_inet_addr * lsraddr,
1065 int labelspace)
1068 ldp_adj *a = MPLS_LIST_HEAD(&g->adj);
1070 while (a != NULL) {
1071 if ((!mpls_inet_addr_compare(lsraddr, &a->remote_lsr_address)) &&
1072 labelspace == a->remote_label_space)
1073 return a;
1075 a = MPLS_LIST_NEXT(&g->adj, a, _global);
1077 return NULL;
1080 mpls_return_enum ldp_global_find_tunnel_index(ldp_global * g, uint32_t index,
1081 ldp_tunnel ** tunnel)
1083 ldp_tunnel *t = NULL;
1085 if (g && index > 0) {
1086 /* because we sort our inserts by index, this lets us know
1087 if we've "walked" past the end of the list */
1089 t = MPLS_LIST_TAIL(&g->tunnel);
1090 if (t == NULL || t->index < index) {
1091 *tunnel = NULL;
1092 return MPLS_END_OF_LIST;
1095 t = MPLS_LIST_HEAD(&g->tunnel);
1096 while (t != NULL) {
1097 if (t->index == index) {
1098 *tunnel = t;
1099 return MPLS_SUCCESS;
1101 t = MPLS_LIST_NEXT(&g->tunnel, t, _global);
1104 *tunnel = NULL;
1105 return MPLS_FAILURE;
1108 mpls_return_enum ldp_global_find_resource_index(ldp_global * g, uint32_t index,
1109 ldp_resource ** resource)
1111 ldp_resource *r = NULL;
1113 if (g && index > 0) {
1114 /* because we sort our inserts by index, this lets us know
1115 if we've "walked" past the end of the list */
1117 r = MPLS_LIST_TAIL(&g->resource);
1118 if (r == NULL || r->index < index) {
1119 *resource = NULL;
1120 return MPLS_END_OF_LIST;
1123 r = MPLS_LIST_HEAD(&g->resource);
1124 while (r != NULL) {
1125 if (r->index == index) {
1126 *resource = r;
1127 return MPLS_SUCCESS;
1129 r = MPLS_LIST_NEXT(&g->resource, r, _global);
1132 *resource = NULL;
1133 return MPLS_FAILURE;
1136 mpls_return_enum ldp_global_find_hop_list_index(ldp_global * g, uint32_t index,
1137 ldp_hop_list ** hop_list)
1139 ldp_hop_list *h = NULL;
1141 if (g && index > 0) {
1142 /* because we sort our inserts by index, this lets us know
1143 if we've "walked" past the end of the list */
1145 h = MPLS_LIST_TAIL(&g->hop_list);
1146 if (h == NULL || h->index < index) {
1147 *hop_list = NULL;
1148 return MPLS_END_OF_LIST;
1151 h = MPLS_LIST_HEAD(&g->hop_list);
1152 while (h != NULL) {
1153 if (h->index == index) {
1154 *hop_list = h;
1155 return MPLS_SUCCESS;
1157 h = MPLS_LIST_NEXT(&g->hop_list, h, _global);
1160 *hop_list = NULL;
1161 return MPLS_FAILURE;
1164 void _ldp_global_add_tunnel(ldp_global * g, ldp_tunnel * t)
1166 ldp_tunnel *tp = NULL;
1168 MPLS_ASSERT(g && t);
1169 MPLS_REFCNT_HOLD(t);
1170 tp = MPLS_LIST_HEAD(&g->tunnel);
1171 while (tp != NULL) {
1172 if (tp->index > t->index) {
1173 MPLS_LIST_INSERT_BEFORE(&g->tunnel, tp, t, _global);
1174 return;
1176 tp = MPLS_LIST_NEXT(&g->tunnel, tp, _global);
1178 MPLS_LIST_ADD_TAIL(&g->tunnel, t, _global, ldp_tunnel);
1181 void _ldp_global_del_tunnel(ldp_global * g, ldp_tunnel * t)
1183 MPLS_ASSERT(g && t);
1184 MPLS_LIST_REMOVE(&g->tunnel, t, _global);
1185 MPLS_REFCNT_RELEASE(t, ldp_tunnel_delete);
1188 void _ldp_global_add_resource(ldp_global * g, ldp_resource * r)
1190 ldp_resource *rp = NULL;
1192 MPLS_ASSERT(g && r);
1193 MPLS_REFCNT_HOLD(r);
1194 rp = MPLS_LIST_HEAD(&g->resource);
1195 while (rp != NULL) {
1196 if (rp->index > r->index) {
1197 MPLS_LIST_INSERT_BEFORE(&g->resource, rp, r, _global);
1198 return;
1200 rp = MPLS_LIST_NEXT(&g->resource, rp, _global);
1202 MPLS_LIST_ADD_TAIL(&g->resource, r, _global, ldp_resource);
1205 void _ldp_global_del_resource(ldp_global * g, ldp_resource * r)
1207 MPLS_ASSERT(g && r);
1208 MPLS_LIST_REMOVE(&g->resource, r, _global);
1209 MPLS_REFCNT_RELEASE(r, ldp_resource_delete);
1212 void _ldp_global_add_hop_list(ldp_global * g, ldp_hop_list * h)
1214 ldp_hop_list *hp = NULL;
1216 MPLS_ASSERT(g && h);
1217 MPLS_REFCNT_HOLD(h);
1218 hp = MPLS_LIST_HEAD(&g->hop_list);
1219 while (hp != NULL) {
1220 if (hp->index > h->index) {
1221 MPLS_LIST_INSERT_BEFORE(&g->hop_list, hp, h, _global);
1222 return;
1224 hp = MPLS_LIST_NEXT(&g->hop_list, hp, _global);
1226 MPLS_LIST_ADD_TAIL(&g->hop_list, h, _global, ldp_hop_list);
1229 void _ldp_global_del_hop_list(ldp_global * g, ldp_hop_list * h)
1231 MPLS_ASSERT(g && h);
1232 MPLS_LIST_REMOVE(&g->hop_list, h, _global);
1233 MPLS_REFCNT_RELEASE(h, ldp_hop_list_delete);
1236 void _ldp_global_add_fec(ldp_global * g, ldp_fec * f)
1238 ldp_fec *fp = NULL;
1240 MPLS_ASSERT(g && f);
1241 MPLS_REFCNT_HOLD(f);
1242 fp = MPLS_LIST_HEAD(&g->fec);
1243 while (fp != NULL) {
1244 if (fp->index > f->index) {
1245 MPLS_LIST_INSERT_BEFORE(&g->fec, fp, f, _global);
1246 return;
1248 fp = MPLS_LIST_NEXT(&g->fec, fp, _global);
1250 MPLS_LIST_ADD_TAIL(&g->fec, f, _global, ldp_fec);
1253 void _ldp_global_del_fec(ldp_global * g, ldp_fec * f)
1255 MPLS_ASSERT(g && f);
1256 MPLS_LIST_REMOVE(&g->fec, f, _global);
1259 void _ldp_global_add_nexthop(ldp_global * g, ldp_nexthop * nh)
1261 ldp_nexthop *nhp = NULL;
1263 MPLS_ASSERT(g && nh);
1264 MPLS_REFCNT_HOLD(nh);
1265 nhp = MPLS_LIST_HEAD(&g->nexthop);
1266 while (nhp != NULL) {
1267 if (nhp->index > nh->index) {
1268 MPLS_LIST_INSERT_BEFORE(&g->nexthop, nhp, nh, _global);
1269 return;
1271 nhp = MPLS_LIST_NEXT(&g->nexthop, nhp, _global);
1273 MPLS_LIST_ADD_TAIL(&g->nexthop, nh, _global, ldp_nexthop);
1276 void _ldp_global_del_nexthop(ldp_global * g, ldp_nexthop * nh)
1278 MPLS_ASSERT(g && nh);
1279 MPLS_LIST_REMOVE(&g->nexthop, nh, _global);
1280 MPLS_REFCNT_RELEASE(nh, ldp_nexthop_delete);