LDP now reacts to FEC adds and deletes
[mpls-ldp-portable.git] / ldp / ldp_global.c
blob9cc875b7e962188a2eb89f1352c9fe5c0db891ea
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_create(g, &fec);
298 if (!f) {
299 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 if (ldp_fec_add_nexthop(g, f, n) != MPLS_SUCCESS) {
310 goto ldp_global_startup_cleanup;
312 _ldp_global_add_nexthop(g, n);
313 } while (mpls_fib_getnext_route(g->fib_handle, &fec, &nexthop) ==
314 MPLS_SUCCESS);
318 e = MPLS_LIST_HEAD(&g->entity);
319 while (e != NULL) {
320 ldp_entity_startup(g, e);
321 e = MPLS_LIST_NEXT(&g->entity, e, _global);
324 g->admin_state = MPLS_ADMIN_ENABLE;
326 LDP_EXIT(g->user_data, "ldp_global_startup");
327 return MPLS_SUCCESS;
329 ldp_global_startup_cleanup:
330 ldp_global_shutdown(g);
331 mpls_socket_close(g->socket_handle, g->hello_socket);
332 mpls_socket_close(g->socket_handle, g->listen_socket);
333 g->hello_socket = 0;
334 g->listen_socket = 0;
336 LDP_EXIT(g->user_data, "ldp_global_startup-error");
338 return MPLS_FAILURE;
341 mpls_return_enum ldp_global_shutdown(ldp_global * g)
343 ldp_entity *e = NULL;
345 MPLS_ASSERT(g);
347 LDP_ENTER(g->user_data, "ldp_global_shutdown");
349 e = MPLS_LIST_HEAD(&g->entity);
350 while (e != NULL) {
351 ldp_entity_shutdown(g, e, 1);
352 e = MPLS_LIST_NEXT(&g->entity, e, _global);
355 g->admin_state = MPLS_ADMIN_DISABLE;
358 ldp_nexthop *n;
359 ldp_fec *f;
360 while ((f = MPLS_LIST_HEAD(&g->fec))) {
361 while ((n = MPLS_LIST_HEAD(&f->nh_root))) {
362 ldp_fec_del_nexthop(g, f, n);
367 ldp_addr *a;
368 ldp_if *i;
369 while ((i = MPLS_LIST_HEAD(&g->iff))) {
370 while ((a = MPLS_LIST_HEAD(&i->addr_root))) {
371 ldp_if_del_addr(g, i, a);
373 ldp_if_remove(g, i);
377 mpls_socket_readlist_del(g->socket_handle, g->hello_socket);
378 mpls_socket_close(g->socket_handle, g->hello_socket);
380 mpls_socket_readlist_del(g->socket_handle, g->listen_socket);
381 mpls_socket_close(g->socket_handle, g->listen_socket);
383 mpls_tree_delete(g->addr_tree);
384 mpls_tree_delete(g->fec_tree);
386 mpls_lock_release(g->global_lock);
387 mpls_timer_close(g->timer_handle);
388 mpls_lock_get(g->global_lock);
390 mpls_socket_mgr_close(g->socket_handle);
391 mpls_ifmgr_close(g->ifmgr_handle);
392 mpls_fib_close(g->fib_handle);
394 #if MPLS_USE_LSR
395 #else
396 mpls_mpls_close(g->mpls_handle);
397 #endif
399 LDP_EXIT(g->user_data, "ldp_global_shutdown");
401 return MPLS_SUCCESS;
404 mpls_return_enum ldp_global_delete(ldp_global * g)
406 if (g) {
407 mpls_lock_delete(g->global_lock);
408 LDP_PRINT(g->user_data, "global delete\n");
409 mpls_free(g);
411 return MPLS_SUCCESS;
414 void _ldp_global_add_attr(ldp_global * g, ldp_attr * a)
416 ldp_attr *ap = NULL;
418 MPLS_ASSERT(g && a);
419 MPLS_REFCNT_HOLD(a);
420 ap = MPLS_LIST_HEAD(&g->attr);
421 while (ap != NULL) {
422 if (ap->index > a->index) {
423 MPLS_LIST_INSERT_BEFORE(&g->attr, ap, a, _global);
424 return;
426 ap = MPLS_LIST_NEXT(&g->attr, ap, _global);
428 MPLS_LIST_ADD_TAIL(&g->attr, a, _global, ldp_attr);
431 void _ldp_global_del_attr(ldp_global * g, ldp_attr * a)
433 MPLS_ASSERT(g && a);
434 MPLS_LIST_REMOVE(&g->attr, a, _global);
435 MPLS_REFCNT_RELEASE(a, ldp_attr_delete);
438 void _ldp_global_add_peer(ldp_global * g, ldp_peer * p)
440 ldp_peer *pp = NULL;
442 MPLS_ASSERT(g && p);
443 MPLS_REFCNT_HOLD(p);
444 pp = MPLS_LIST_HEAD(&g->peer);
445 while (pp != NULL) {
446 if (pp->index > p->index) {
447 MPLS_LIST_INSERT_BEFORE(&g->peer, pp, p, _global);
448 return;
450 pp = MPLS_LIST_NEXT(&g->peer, pp, _global);
452 MPLS_LIST_ADD_TAIL(&g->peer, p, _global, ldp_peer);
455 void _ldp_global_del_peer(ldp_global * g, ldp_peer * p)
457 MPLS_ASSERT(g && p);
458 MPLS_LIST_REMOVE(&g->peer, p, _global);
459 MPLS_REFCNT_RELEASE(p, ldp_peer_delete);
463 * _ldp_global_add_if/del_if and _ldp_global_add_addr/del_addr are
464 * not the same as the rest of the global_add/del functions. They
465 * do not hold refcnts, they are used as part of the create and delete
466 * process of these structures
469 void _ldp_global_add_if(ldp_global * g, ldp_if * i)
471 ldp_if *ip = NULL;
473 MPLS_ASSERT(g && i);
474 ip = MPLS_LIST_HEAD(&g->iff);
475 while (ip != NULL) {
476 if (ip->index > i->index) {
477 MPLS_LIST_INSERT_BEFORE(&g->iff, ip, i, _global);
478 return;
480 ip = MPLS_LIST_NEXT(&g->iff, ip, _global);
482 MPLS_LIST_ADD_TAIL(&g->iff, i, _global, ldp_if);
485 void _ldp_global_del_if(ldp_global * g, ldp_if * i)
487 MPLS_ASSERT(g && i);
488 MPLS_LIST_REMOVE(&g->iff, i, _global);
491 void _ldp_global_add_addr(ldp_global * g, ldp_addr * a)
493 ldp_addr *ap = NULL;
495 MPLS_ASSERT(g && a);
496 ap = MPLS_LIST_HEAD(&g->addr);
497 while (ap != NULL) {
498 if (ap->index > a->index) {
499 MPLS_LIST_INSERT_BEFORE(&g->addr, ap, a, _global);
500 return;
502 ap = MPLS_LIST_NEXT(&g->addr, ap, _global);
504 MPLS_LIST_ADD_TAIL(&g->addr, a, _global, ldp_addr);
507 void _ldp_global_del_addr(ldp_global * g, ldp_addr * a)
509 MPLS_ASSERT(g && a);
510 MPLS_LIST_REMOVE(&g->addr, a, _global);
515 void _ldp_global_add_adj(ldp_global * g, ldp_adj * a)
517 ldp_adj *ap = NULL;
519 MPLS_ASSERT(g && a);
520 MPLS_REFCNT_HOLD(a);
521 ap = MPLS_LIST_HEAD(&g->adj);
522 while (ap != NULL) {
523 if (ap->index > a->index) {
524 MPLS_LIST_INSERT_BEFORE(&g->adj, ap, a, _global);
525 return;
527 ap = MPLS_LIST_NEXT(&g->adj, ap, _global);
529 MPLS_LIST_ADD_TAIL(&g->adj, a, _global, ldp_adj);
532 void _ldp_global_del_adj(ldp_global * g, ldp_adj * a)
534 MPLS_ASSERT(g && a);
535 MPLS_LIST_REMOVE(&g->adj, a, _global);
536 MPLS_REFCNT_RELEASE(a, ldp_adj_delete);
539 void _ldp_global_add_entity(ldp_global * g, ldp_entity * e)
541 ldp_entity *ep = NULL;
543 MPLS_ASSERT(g && e);
544 MPLS_REFCNT_HOLD(e);
545 ep = MPLS_LIST_HEAD(&g->entity);
546 while (ep != NULL) {
547 if (ep->index > e->index) {
548 MPLS_LIST_INSERT_BEFORE(&g->entity, ep, e, _global);
549 return;
551 ep = MPLS_LIST_NEXT(&g->entity, ep, _global);
553 MPLS_LIST_ADD_TAIL(&g->entity, e, _global, ldp_entity);
556 void _ldp_global_del_entity(ldp_global * g, ldp_entity * e)
558 MPLS_ASSERT(g && e);
559 MPLS_LIST_REMOVE(&g->entity, e, _global);
560 MPLS_REFCNT_RELEASE(e, ldp_entity_delete);
563 void _ldp_global_add_session(ldp_global * g, ldp_session * s)
565 ldp_session *sp = NULL;
567 MPLS_ASSERT(g && s);
568 MPLS_REFCNT_HOLD(s);
569 s->on_global = MPLS_BOOL_TRUE;
570 sp = MPLS_LIST_HEAD(&g->session);
571 while (sp != NULL) {
572 if (sp->index > s->index) {
573 MPLS_LIST_INSERT_BEFORE(&g->session, sp, s, _global);
574 return;
576 sp = MPLS_LIST_NEXT(&g->session, sp, _global);
578 MPLS_LIST_ADD_TAIL(&g->session, s, _global, ldp_session);
581 void _ldp_global_del_session(ldp_global * g, ldp_session * s)
583 MPLS_ASSERT(g && s);
584 MPLS_ASSERT(s->on_global == MPLS_BOOL_TRUE);
585 MPLS_LIST_REMOVE(&g->session, s, _global);
586 s->on_global = MPLS_BOOL_FALSE;
587 MPLS_REFCNT_RELEASE(s, ldp_session_delete);
590 mpls_return_enum _ldp_global_add_inlabel(ldp_global * g, ldp_inlabel * i)
592 ldp_inlabel *ip = NULL;
593 mpls_return_enum result;
595 MPLS_ASSERT(g && i);
597 #if MPLS_USE_LSR
599 lsr_insegment iseg;
600 memcpy(&iseg.info,&i->info,sizeof(mpls_insegment));
601 result = lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_ADD|
602 LSR_INSEGMENT_CFG_NPOP|LSR_INSEGMENT_CFG_FAMILY|
603 LSR_INSEGMENT_CFG_LABELSPACE|LSR_INSEGMENT_CFG_LABEL|
604 LSR_INSEGMENT_CFG_OWNER);
605 memcpy(&i->info, &iseg.info, sizeof(mpls_insegment));
606 i->info.handle = iseg.index;
608 #else
609 result = mpls_mpls_insegment_add(g->mpls_handle, &i->info);
610 #endif
611 if (result != MPLS_SUCCESS) {
612 return result;
615 MPLS_REFCNT_HOLD(i);
616 ip = MPLS_LIST_HEAD(&g->inlabel);
617 while (ip != NULL) {
618 if (ip->index > i->index) {
619 MPLS_LIST_INSERT_BEFORE(&g->inlabel, ip, i, _global);
620 return MPLS_SUCCESS;
622 ip = MPLS_LIST_NEXT(&g->inlabel, ip, _global);
624 MPLS_LIST_ADD_TAIL(&g->inlabel, i, _global, ldp_inlabel);
625 return MPLS_SUCCESS;
628 mpls_return_enum _ldp_global_del_inlabel(ldp_global * g, ldp_inlabel * i)
630 MPLS_ASSERT(g && i);
631 MPLS_ASSERT(i->reuse_count == 0);
632 #if MPLS_USE_LSR
634 lsr_insegment iseg;
635 iseg.index = i->info.handle;
636 lsr_cfg_insegment_set(g->lsr_handle, &iseg, LSR_CFG_DEL);
638 #else
639 mpls_mpls_insegment_del(g->mpls_handle, &i->info);
640 #endif
641 MPLS_LIST_REMOVE(&g->inlabel, i, _global);
642 MPLS_REFCNT_RELEASE(i, ldp_inlabel_delete);
643 return MPLS_SUCCESS;
646 mpls_return_enum _ldp_global_add_outlabel(ldp_global * g, ldp_outlabel * o)
648 ldp_outlabel *op = NULL;
649 mpls_return_enum result;
651 MPLS_ASSERT(g && o);
652 #if MPLS_USE_LSR
654 lsr_outsegment oseg;
655 memcpy(&oseg.info, &o->info, sizeof(mpls_outsegment));
656 result = lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_ADD|
657 LSR_OUTSEGMENT_CFG_PUSH_LABEL|LSR_OUTSEGMENT_CFG_OWNER|
658 LSR_OUTSEGMENT_CFG_INTERFACE|LSR_OUTSEGMENT_CFG_LABEL|
659 LSR_OUTSEGMENT_CFG_NEXTHOP);
660 o->info.handle = oseg.index;
662 #else
663 result = mpls_mpls_outsegment_add(g->mpls_handle, &o->info);
664 #endif
666 if (result != MPLS_SUCCESS) {
667 return result;
670 MPLS_REFCNT_HOLD(o);
671 o->switching = MPLS_BOOL_TRUE;
672 op = MPLS_LIST_HEAD(&g->outlabel);
673 while (op != NULL) {
674 if (op->index > o->index) {
675 MPLS_LIST_INSERT_BEFORE(&g->outlabel, op, o, _global);
676 return MPLS_SUCCESS;
678 op = MPLS_LIST_NEXT(&g->outlabel, op, _global);
680 MPLS_LIST_ADD_TAIL(&g->outlabel, o, _global, ldp_outlabel);
681 return MPLS_SUCCESS;
684 mpls_return_enum _ldp_global_del_outlabel(ldp_global * g, ldp_outlabel * o)
686 MPLS_ASSERT(g && o);
687 #if MPLS_USE_LSR
689 lsr_outsegment oseg;
690 oseg.index = o->info.handle;
691 lsr_cfg_outsegment_set(g->lsr_handle, &oseg, LSR_CFG_DEL);
693 #else
694 mpls_mpls_outsegment_del(g->mpls_handle, &o->info);
695 #endif
697 o->switching = MPLS_BOOL_FALSE;
698 MPLS_ASSERT(o->merge_count == 0);
699 MPLS_LIST_REMOVE(&g->outlabel, o, _global);
700 MPLS_REFCNT_RELEASE(o, ldp_outlabel_delete);
701 return MPLS_SUCCESS;
704 mpls_return_enum ldp_global_find_attr_index(ldp_global * g, uint32_t index,
705 ldp_attr ** attr)
707 ldp_attr *a = NULL;
709 if (g && index > 0) {
711 /* because we sort our inserts by index, this lets us know
712 if we've "walked" past the end of the list */
714 a = MPLS_LIST_TAIL(&g->attr);
715 if (a == NULL || a->index < index) {
716 return MPLS_END_OF_LIST;
717 *attr = NULL;
720 a = MPLS_LIST_HEAD(&g->attr);
721 while (a != NULL) {
722 if (a->index == index) {
723 *attr = a;
724 return MPLS_SUCCESS;
726 a = MPLS_LIST_NEXT(&g->attr, a, _global);
729 *attr = NULL;
730 return MPLS_FAILURE;
733 mpls_return_enum ldp_global_find_session_index(ldp_global * g, uint32_t index,
734 ldp_session ** session)
736 ldp_session *s = NULL;
738 if (g && index > 0) {
740 /* because we sort our inserts by index, this lets us know
741 if we've "walked" past the end of the list */
743 s = MPLS_LIST_TAIL(&g->session);
744 if (s == NULL || s->index < index) {
745 *session = NULL;
746 return MPLS_END_OF_LIST;
749 s = MPLS_LIST_HEAD(&g->session);
750 while (s != NULL) {
751 if (s->index == index) {
752 *session = s;
753 return MPLS_SUCCESS;
755 s = MPLS_LIST_NEXT(&g->session, s, _global);
758 *session = NULL;
759 return MPLS_FAILURE;
762 mpls_return_enum ldp_global_find_inlabel_index(ldp_global * g, uint32_t index,
763 ldp_inlabel ** inlabel)
765 ldp_inlabel *i = NULL;
767 if (g && index > 0) {
769 /* because we sort our inserts by index, this lets us know
770 if we've "walked" past the end of the list */
772 i = MPLS_LIST_TAIL(&g->inlabel);
773 if (i == NULL || i->index < index) {
774 *inlabel = NULL;
775 return MPLS_END_OF_LIST;
778 i = MPLS_LIST_HEAD(&g->inlabel);
779 while (i != NULL) {
780 if (i->index == index) {
781 *inlabel = i;
782 return MPLS_SUCCESS;
784 i = MPLS_LIST_NEXT(&g->inlabel, i, _global);
787 *inlabel = NULL;
788 return MPLS_FAILURE;
791 mpls_return_enum ldp_global_find_outlabel_index(ldp_global * g, uint32_t index,
792 ldp_outlabel ** outlabel)
794 ldp_outlabel *o = NULL;
796 if (g && index > 0) {
798 /* because we sort our inserts by index, this lets us know
799 if we've "walked" past the end of the list */
801 o = MPLS_LIST_TAIL(&g->outlabel);
802 if (o == NULL || o->index < index) {
803 *outlabel = NULL;
804 return MPLS_END_OF_LIST;
807 o = MPLS_LIST_HEAD(&g->outlabel);
808 while (o != NULL) {
809 if (o->index == index) {
810 *outlabel = o;
811 return MPLS_SUCCESS;
813 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
816 *outlabel = NULL;
817 return MPLS_FAILURE;
820 ldp_outlabel *ldp_global_find_outlabel_handle(ldp_global * g,
821 mpls_outsegment_handle handle)
823 ldp_outlabel *o = MPLS_LIST_HEAD(&g->outlabel);
825 if (g) {
826 while (o != NULL) {
827 if (!mpls_outsegment_handle_compare(o->info.handle, handle))
828 return o;
830 o = MPLS_LIST_NEXT(&g->outlabel, o, _global);
833 return NULL;
836 mpls_return_enum ldp_global_find_entity_index(ldp_global * g, uint32_t index,
837 ldp_entity ** entity)
839 ldp_entity *e = NULL;
841 if (g && index > 0) {
843 /* because we sort our inserts by index, this lets us know
844 if we've "walked" past the end of the list */
846 e = MPLS_LIST_TAIL(&g->entity);
847 if (e == NULL || e->index < index) {
848 *entity = NULL;
849 return MPLS_END_OF_LIST;
852 e = MPLS_LIST_HEAD(&g->entity);
853 while (e != NULL) {
854 if (e->index == index) {
855 *entity = e;
856 return MPLS_SUCCESS;
858 e = MPLS_LIST_NEXT(&g->entity, e, _global);
861 *entity = NULL;
862 return MPLS_FAILURE;
865 ldp_peer *ldp_global_find_peer_addr(ldp_global * g, mpls_inet_addr * addr)
867 ldp_peer *p;
869 MPLS_ASSERT(g && addr);
871 /* JLEU: we will need to add a tree to optimize this search,
872 known peers will be in tree, unknown will take a "slow path" to
873 verify them, then be added to tree */
875 p = MPLS_LIST_HEAD(&g->peer);
876 while (p) {
877 LDP_PRINT(g->user_data,
878 "ldp_global_find_peer_lsrid: peer: %08x lsrid: %08x\n",
879 p->dest.addr.u.ipv4, addr->u.ipv4);
880 if (!mpls_inet_addr_compare(&p->dest.addr, addr)) {
881 return p;
883 p = MPLS_LIST_NEXT(&g->peer, p, _global);
885 return NULL;
888 mpls_return_enum ldp_global_find_adj_index(ldp_global * g, uint32_t index,
889 ldp_adj ** adj)
891 ldp_adj *a = NULL;
893 if (g && index > 0) {
894 /* because we sort our inserts by index, this lets us know
895 if we've "walked" past the end of the list */
897 a = MPLS_LIST_TAIL(&g->adj);
898 if (a == NULL || a->index < index) {
899 return MPLS_END_OF_LIST;
900 *adj = NULL;
903 a = MPLS_LIST_HEAD(&g->adj);
904 while (a != NULL) {
905 if (a->index == index) {
906 *adj = a;
907 return MPLS_SUCCESS;
909 a = MPLS_LIST_NEXT(&g->adj, a, _global);
912 *adj = NULL;
913 return MPLS_FAILURE;
916 mpls_return_enum ldp_global_find_peer_index(ldp_global * g, uint32_t index,
917 ldp_peer ** peer)
919 ldp_peer *p = NULL;
921 if (g && index > 0) {
922 /* because we sort our inserts by index, this lets us know
923 if we've "walked" past the end of the list */
925 p = MPLS_LIST_TAIL(&g->peer);
926 if (p == NULL || p->index < index) {
927 *peer = NULL;
928 return MPLS_END_OF_LIST;
931 p = MPLS_LIST_HEAD(&g->peer);
932 while (p != NULL) {
933 if (p->index == index) {
934 *peer = p;
935 return MPLS_SUCCESS;
937 p = MPLS_LIST_NEXT(&g->peer, p, _global);
940 *peer = NULL;
941 return MPLS_FAILURE;
944 mpls_return_enum ldp_global_find_fec_index(ldp_global * g, uint32_t index,
945 ldp_fec ** fec)
947 ldp_fec *f = NULL;
949 if (g && index > 0) {
950 /* because we sort our inserts by index, this lets us know
951 if we've "walked" past the end of the list */
953 f = MPLS_LIST_TAIL(&g->fec);
954 if (f == NULL || f->index < index) {
955 *fec = NULL;
956 return MPLS_END_OF_LIST;
959 f = MPLS_LIST_HEAD(&g->fec);
960 while (f != NULL) {
961 if (f->index == index) {
962 *fec = f;
963 return MPLS_SUCCESS;
965 f = MPLS_LIST_NEXT(&g->fec, f, _global);
968 *fec = NULL;
969 return MPLS_FAILURE;
972 mpls_return_enum ldp_global_find_fec(ldp_global * g, mpls_fec * m,
973 ldp_fec ** fec)
975 ldp_fec *f = NULL;
977 MPLS_ASSERT(g && m);
979 f = MPLS_LIST_HEAD(&g->fec);
980 do {
981 if (!mpls_fec_compare(m, &f->info)) {
982 *fec = f;
983 return MPLS_SUCCESS;
985 } while((f = MPLS_LIST_NEXT(&g->fec, f, _global)));
986 *fec = NULL;
987 return MPLS_FAILURE;
990 mpls_return_enum ldp_global_find_addr_index(ldp_global * g, uint32_t index,
991 ldp_addr ** addr)
993 ldp_addr *a = NULL;
995 if (g && index > 0) {
997 /* because we sort our inserts by index, this lets us know
998 if we've "walked" past the end of the list */
1000 a = MPLS_LIST_TAIL(&g->addr);
1001 if (a == NULL || a->index < index) {
1002 *addr = NULL;
1003 return MPLS_END_OF_LIST;
1006 a = MPLS_LIST_HEAD(&g->addr);
1007 while (a != NULL) {
1008 if (a->index == index) {
1009 *addr = a;
1010 return MPLS_SUCCESS;
1012 a = MPLS_LIST_NEXT(&g->addr, a, _global);
1015 *addr = NULL;
1016 return MPLS_FAILURE;
1019 mpls_return_enum ldp_global_find_if_index(ldp_global * g, uint32_t index,
1020 ldp_if ** iff)
1022 ldp_if *i = NULL;
1024 if (g && index > 0) {
1026 /* because we sort our inserts by index, this lets us know
1027 if we've "walked" past the end of the list */
1029 i = MPLS_LIST_TAIL(&g->iff);
1030 if (i == NULL || i->index < index) {
1031 *iff = NULL;
1032 return MPLS_END_OF_LIST;
1035 i = MPLS_LIST_HEAD(&g->iff);
1036 while (i != NULL) {
1037 if (i->index == index) {
1038 *iff = i;
1039 return MPLS_SUCCESS;
1041 i = MPLS_LIST_NEXT(&g->iff, i, _global);
1044 *iff = NULL;
1045 return MPLS_FAILURE;
1048 ldp_if *ldp_global_find_if_handle(ldp_global * g, mpls_if_handle handle)
1050 ldp_if *i = MPLS_LIST_HEAD(&g->iff);
1052 if (g) {
1053 while (i != NULL) {
1054 if (!mpls_if_handle_compare(i->handle, handle))
1055 return i;
1057 i = MPLS_LIST_NEXT(&g->iff, i, _global);
1060 return NULL;
1063 ldp_adj *ldp_global_find_adj_ldpid(ldp_global * g, mpls_inet_addr * lsraddr,
1064 int labelspace)
1067 ldp_adj *a = MPLS_LIST_HEAD(&g->adj);
1069 while (a != NULL) {
1070 if ((!mpls_inet_addr_compare(lsraddr, &a->remote_lsr_address)) &&
1071 labelspace == a->remote_label_space)
1072 return a;
1074 a = MPLS_LIST_NEXT(&g->adj, a, _global);
1076 return NULL;
1079 mpls_return_enum ldp_global_find_tunnel_index(ldp_global * g, uint32_t index,
1080 ldp_tunnel ** tunnel)
1082 ldp_tunnel *t = NULL;
1084 if (g && index > 0) {
1085 /* because we sort our inserts by index, this lets us know
1086 if we've "walked" past the end of the list */
1088 t = MPLS_LIST_TAIL(&g->tunnel);
1089 if (t == NULL || t->index < index) {
1090 *tunnel = NULL;
1091 return MPLS_END_OF_LIST;
1094 t = MPLS_LIST_HEAD(&g->tunnel);
1095 while (t != NULL) {
1096 if (t->index == index) {
1097 *tunnel = t;
1098 return MPLS_SUCCESS;
1100 t = MPLS_LIST_NEXT(&g->tunnel, t, _global);
1103 *tunnel = NULL;
1104 return MPLS_FAILURE;
1107 mpls_return_enum ldp_global_find_resource_index(ldp_global * g, uint32_t index,
1108 ldp_resource ** resource)
1110 ldp_resource *r = NULL;
1112 if (g && index > 0) {
1113 /* because we sort our inserts by index, this lets us know
1114 if we've "walked" past the end of the list */
1116 r = MPLS_LIST_TAIL(&g->resource);
1117 if (r == NULL || r->index < index) {
1118 *resource = NULL;
1119 return MPLS_END_OF_LIST;
1122 r = MPLS_LIST_HEAD(&g->resource);
1123 while (r != NULL) {
1124 if (r->index == index) {
1125 *resource = r;
1126 return MPLS_SUCCESS;
1128 r = MPLS_LIST_NEXT(&g->resource, r, _global);
1131 *resource = NULL;
1132 return MPLS_FAILURE;
1135 mpls_return_enum ldp_global_find_hop_list_index(ldp_global * g, uint32_t index,
1136 ldp_hop_list ** hop_list)
1138 ldp_hop_list *h = NULL;
1140 if (g && index > 0) {
1141 /* because we sort our inserts by index, this lets us know
1142 if we've "walked" past the end of the list */
1144 h = MPLS_LIST_TAIL(&g->hop_list);
1145 if (h == NULL || h->index < index) {
1146 *hop_list = NULL;
1147 return MPLS_END_OF_LIST;
1150 h = MPLS_LIST_HEAD(&g->hop_list);
1151 while (h != NULL) {
1152 if (h->index == index) {
1153 *hop_list = h;
1154 return MPLS_SUCCESS;
1156 h = MPLS_LIST_NEXT(&g->hop_list, h, _global);
1159 *hop_list = NULL;
1160 return MPLS_FAILURE;
1163 void _ldp_global_add_tunnel(ldp_global * g, ldp_tunnel * t)
1165 ldp_tunnel *tp = NULL;
1167 MPLS_ASSERT(g && t);
1168 MPLS_REFCNT_HOLD(t);
1169 tp = MPLS_LIST_HEAD(&g->tunnel);
1170 while (tp != NULL) {
1171 if (tp->index > t->index) {
1172 MPLS_LIST_INSERT_BEFORE(&g->tunnel, tp, t, _global);
1173 return;
1175 tp = MPLS_LIST_NEXT(&g->tunnel, tp, _global);
1177 MPLS_LIST_ADD_TAIL(&g->tunnel, t, _global, ldp_tunnel);
1180 void _ldp_global_del_tunnel(ldp_global * g, ldp_tunnel * t)
1182 MPLS_ASSERT(g && t);
1183 MPLS_LIST_REMOVE(&g->tunnel, t, _global);
1184 MPLS_REFCNT_RELEASE(t, ldp_tunnel_delete);
1187 void _ldp_global_add_resource(ldp_global * g, ldp_resource * r)
1189 ldp_resource *rp = NULL;
1191 MPLS_ASSERT(g && r);
1192 MPLS_REFCNT_HOLD(r);
1193 rp = MPLS_LIST_HEAD(&g->resource);
1194 while (rp != NULL) {
1195 if (rp->index > r->index) {
1196 MPLS_LIST_INSERT_BEFORE(&g->resource, rp, r, _global);
1197 return;
1199 rp = MPLS_LIST_NEXT(&g->resource, rp, _global);
1201 MPLS_LIST_ADD_TAIL(&g->resource, r, _global, ldp_resource);
1204 void _ldp_global_del_resource(ldp_global * g, ldp_resource * r)
1206 MPLS_ASSERT(g && r);
1207 MPLS_LIST_REMOVE(&g->resource, r, _global);
1208 MPLS_REFCNT_RELEASE(r, ldp_resource_delete);
1211 void _ldp_global_add_hop_list(ldp_global * g, ldp_hop_list * h)
1213 ldp_hop_list *hp = NULL;
1215 MPLS_ASSERT(g && h);
1216 MPLS_REFCNT_HOLD(h);
1217 hp = MPLS_LIST_HEAD(&g->hop_list);
1218 while (hp != NULL) {
1219 if (hp->index > h->index) {
1220 MPLS_LIST_INSERT_BEFORE(&g->hop_list, hp, h, _global);
1221 return;
1223 hp = MPLS_LIST_NEXT(&g->hop_list, hp, _global);
1225 MPLS_LIST_ADD_TAIL(&g->hop_list, h, _global, ldp_hop_list);
1228 void _ldp_global_del_hop_list(ldp_global * g, ldp_hop_list * h)
1230 MPLS_ASSERT(g && h);
1231 MPLS_LIST_REMOVE(&g->hop_list, h, _global);
1232 MPLS_REFCNT_RELEASE(h, ldp_hop_list_delete);
1235 void _ldp_global_add_fec(ldp_global * g, ldp_fec * f)
1237 ldp_fec *fp = NULL;
1239 MPLS_ASSERT(g && f);
1240 MPLS_REFCNT_HOLD(f);
1241 fp = MPLS_LIST_HEAD(&g->fec);
1242 while (fp != NULL) {
1243 if (fp->index > f->index) {
1244 MPLS_LIST_INSERT_BEFORE(&g->fec, fp, f, _global);
1245 return;
1247 fp = MPLS_LIST_NEXT(&g->fec, fp, _global);
1249 MPLS_LIST_ADD_TAIL(&g->fec, f, _global, ldp_fec);
1252 void _ldp_global_del_fec(ldp_global * g, ldp_fec * f)
1254 MPLS_ASSERT(g && f);
1255 MPLS_LIST_REMOVE(&g->fec, f, _global);
1258 void _ldp_global_add_nexthop(ldp_global * g, ldp_nexthop * nh)
1260 ldp_nexthop *nhp = NULL;
1262 MPLS_ASSERT(g && nh);
1263 MPLS_REFCNT_HOLD(nh);
1264 nhp = MPLS_LIST_HEAD(&g->nexthop);
1265 while (nhp != NULL) {
1266 if (nhp->index > nh->index) {
1267 MPLS_LIST_INSERT_BEFORE(&g->nexthop, nhp, nh, _global);
1268 return;
1270 nhp = MPLS_LIST_NEXT(&g->nexthop, nhp, _global);
1272 MPLS_LIST_ADD_TAIL(&g->nexthop, nh, _global, ldp_nexthop);
1275 void _ldp_global_del_nexthop(ldp_global * g, ldp_nexthop * nh)
1277 MPLS_ASSERT(g && nh);
1278 MPLS_LIST_REMOVE(&g->nexthop, nh, _global);
1279 MPLS_REFCNT_RELEASE(nh, ldp_nexthop_delete);