Don't allow the user to delete a fec that still has nexthops
[mpls-ldp-portable.git] / ldp / ldp_global.c
blob945fb4eadc372dead960765a871ce150144684f9
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);
258 #if 0
260 mpls_if_handle iff;
261 mpls_inet_addr addr;
262 mpls_return_enum retval;
264 retval = mpls_ifmgr_getfirst_address(g->ifmgr_handle, &iff, &addr);
265 if (retval == MPLS_FATAL) {
266 goto ldp_global_startup_cleanup;
268 if (retval == MPLS_SUCCESS) {
269 do {
270 ldp_addr *a;
271 ldp_if *i;
272 if (!(a = ldp_addr_create(g, &addr))) {
273 goto ldp_global_startup_cleanup;
275 a->if_handle = iff;
276 if ((i = ldp_global_find_if_handle(g, iff))) {
277 ldp_if_add_addr(i, a);
279 } while (mpls_ifmgr_getnext_address(g->ifmgr_handle, &iff, &addr) ==
280 MPLS_SUCCESS);
284 mpls_fec fec;
285 mpls_nexthop nexthop;
286 mpls_return_enum retval;
288 retval = mpls_fib_getfirst_route(g->fib_handle, &fec, &nexthop);
289 if (retval == MPLS_FATAL) {
290 goto ldp_global_startup_cleanup;
292 if (retval == MPLS_SUCCESS) {
293 do {
294 ldp_nexthop *n;
295 ldp_fec *f;
297 if (!(f = ldp_fec_find(g, &fec))) {
298 f = ldp_fec_create(g, &fec);
299 if (!f) {
300 goto ldp_global_startup_cleanup;
304 n = ldp_nexthop_create();
305 if (!n) {
306 goto ldp_global_startup_cleanup;
309 memcpy(&n->info, &nexthop, sizeof(mpls_nexthop));
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);
318 #endif
320 e = MPLS_LIST_HEAD(&g->entity);
321 while (e != NULL) {
322 ldp_entity_startup(g, e);
323 e = MPLS_LIST_NEXT(&g->entity, e, _global);
326 g->admin_state = MPLS_ADMIN_ENABLE;
328 LDP_EXIT(g->user_data, "ldp_global_startup");
329 return MPLS_SUCCESS;
331 ldp_global_startup_cleanup:
332 ldp_global_shutdown(g);
333 mpls_socket_close(g->socket_handle, g->hello_socket);
334 mpls_socket_close(g->socket_handle, g->listen_socket);
335 g->hello_socket = 0;
336 g->listen_socket = 0;
338 LDP_EXIT(g->user_data, "ldp_global_startup-error");
340 return MPLS_FAILURE;
343 mpls_return_enum ldp_global_shutdown(ldp_global * g)
345 ldp_entity *e = NULL;
346 ldp_nexthop *n;
347 ldp_fec *f;
348 ldp_addr *a;
349 ldp_if *i;
351 MPLS_ASSERT(g);
353 LDP_ENTER(g->user_data, "ldp_global_shutdown");
355 e = MPLS_LIST_HEAD(&g->entity);
356 while (e != NULL) {
357 ldp_entity_shutdown(g, e, 1);
358 e = MPLS_LIST_NEXT(&g->entity, e, _global);
361 g->admin_state = MPLS_ADMIN_DISABLE;
363 while ((f = MPLS_LIST_HEAD(&g->fec))) {
364 while ((n = MPLS_LIST_HEAD(&f->nh_root))) {
365 ldp_fec_del_nexthop(g, f, n);
367 MPLS_REFCNT_RELEASE2(g, f, ldp_fec_delete);
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 MPLS_REFCNT_RELEASE2(g, i, ldp_if_delete);
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);
1241 * TESTING: jleu 6/7/2004, since I want the FEC to be cleaned up
1242 * when it no longer has a nexthop, addr, or label, the only things that
1243 * should increment the ref are those (nh, addr, label etc), not global
1244 * nor inserting into the tree. I also added this comment in
1245 * ldp_fec_create()
1246 MPLS_REFCNT_HOLD(f);
1248 fp = MPLS_LIST_HEAD(&g->fec);
1249 while (fp != NULL) {
1250 if (fp->index > f->index) {
1251 MPLS_LIST_INSERT_BEFORE(&g->fec, fp, f, _global);
1252 return;
1254 fp = MPLS_LIST_NEXT(&g->fec, fp, _global);
1256 MPLS_LIST_ADD_TAIL(&g->fec, f, _global, ldp_fec);
1259 void _ldp_global_del_fec(ldp_global * g, ldp_fec * f)
1261 MPLS_ASSERT(g && f);
1262 MPLS_LIST_REMOVE(&g->fec, f, _global);
1265 void _ldp_global_add_nexthop(ldp_global * g, ldp_nexthop * nh)
1267 ldp_nexthop *nhp = NULL;
1269 MPLS_ASSERT(g && 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);